Search code examples
pythonoauth-2.0sha256hmachashlib

Changing python script TBA SHA1 to SHA256


I was recently hired as a junior dev as my first job for a bigger company which uses NetSuite. An old dev wrote a python script which handles pictures made by designers, that uploads pictures to NetSuite when they are uploaded to a specific folder.

Since the Script uses SHA1 I need to change the TBA to SHA256 because NetSuite does not support SHA1 anymore.

I have a hard time understanding the old dev's code, and find documentation on how to change the TBA from SHA1 to SHA256..

These are snippets from the code.

import datetime
import requests
import os
import oauth2 as oauth
import json
import time
import base64
import sys
import hashlib
import hmac
    url = "https://xxxxx=1"
token = oauth.Token(key="xxxxxxxxxxx",secret="xxxxxxxxxx")
consumer = oauth.Consumer(key="xxxxxxxxxxxxxxxx",secret="xxxxxxxxxxxxxxxx")
realm="xxxxxxxxxxxxxx"
signature_method = oauth.SignatureMethod_HMAC_SHA1()

In this part I understand he initialises the method oauth.SignatureMethod_HMAC_SHA1().

Then when I go to the oauth file I find this

class SignatureMethod_HMAC_SHA1(SignatureMethod):
    name = 'HMAC-SHA1'

    def signing_base(self, request, consumer, token):
        if (not hasattr(request, 'normalized_url') or request.normalized_url is None):
            raise ValueError("Base URL for request is not set.")

        sig = (
            escape(request.method),
            escape(request.normalized_url),
            escape(request.get_normalized_parameters()),
        )

        key = '%s&' % escape(consumer.secret)
        if token:
            key += escape(token.secret)
        raw = '&'.join(sig)
        return key.encode('ascii'), raw.encode('ascii')

    def sign(self, request, consumer, token):
        """Builds the base signature string."""
        key, raw = self.signing_base(request, consumer, token)

        hashed = hmac.new(key, raw, sha1)

        # Calculate the digest base 64.
        return binascii.b2a_base64(hashed.digest())[:-1]

I looked this file through, and it does not contain any methods containing SHA256.. Only SHA1 and PLAINTEXT.

I tried to change the values to SHA256 but that did not work of course. I tried to look up documentation on oAuth2 but I only found very small amounts of information, and it seems like it only contains SHA1 and PLAINTEXT..

So how do I change the script to function with SHA256 instead of SHA1?

EDIT to answer comment Hashlib contains this:

    class _Hash(object):
    digest_size: int
    block_size: int

    # [Python documentation note] Changed in version 3.4: The name attribute has
    # been present in CPython since its inception, but until Python 3.4 was not
    # formally specified, so may not exist on some platforms
    name: str

    def __init__(self, data: _DataType = ...) -> None: ...

    def copy(self) -> _Hash: ...
    def digest(self) -> bytes: ...
    def hexdigest(self) -> str: ...
    def update(self, arg: _DataType) -> None: ...

def md5(arg: _DataType = ...) -> _Hash: ...
def sha1(arg: _DataType = ...) -> _Hash: ...
def sha224(arg: _DataType = ...) -> _Hash: ...
def sha256(arg: _DataType = ...) -> _Hash: ...
def sha384(arg: _DataType = ...) -> _Hash: ...
def sha512(arg: _DataType = ...) -> _Hash: ...

def new(name: str, data: _DataType = ...) -> _Hash: ...

algorithms_guaranteed: AbstractSet[str]
algorithms_available: AbstractSet[str]

def pbkdf2_hmac(hash_name: str, password: _DataType, salt: _DataType, iterations: int, dklen: Optional[int] = ...) -> bytes: ...

if sys.version_info >= (3, 6):
    class _VarLenHash(object):
        digest_size: int
        block_size: int
        name: str

        def __init__(self, data: _DataType = ...) -> None: ...

        def copy(self) -> _VarLenHash: ...
        def digest(self, length: int) -> bytes: ...
        def hexdigest(self, length: int) -> str: ...
        def update(self, arg: _DataType) -> None: ...

    sha3_224 = _Hash
    sha3_256 = _Hash
    sha3_384 = _Hash
    sha3_512 = _Hash
    shake_128 = _VarLenHash
    shake_256 = _VarLenHash

    def scrypt(password: _DataType, *, salt: _DataType, n: int, r: int, p: int, maxmem: int = ..., dklen: int = ...) -> bytes: ...

    class _BlakeHash(_Hash):
        MAX_DIGEST_SIZE: int
        MAX_KEY_SIZE: int
        PERSON_SIZE: int
        SALT_SIZE: int

        def __init__(self, data: _DataType = ..., digest_size: int = ..., key: _DataType = ..., salt: _DataType = ..., person: _DataType = ..., fanout: int = ..., depth: int = ..., leaf_size: int = ..., node_offset: int = ..., node_depth: int = ..., inner_size: int = ..., last_node: bool = ...) -> None: ...

    blake2b = _BlakeHash
    blake2s = _BlakeHash

Solution

  • There is already sha256() function in Haslib file, so you can try to add a new class SignatureMethod_HMAC_SHA256 into the oauth file which can be similar to that SHA1.

    Just change parameters of hmac.new() function like this:

    hashed = hmac.new(key, raw, sha256)
    

    Whole class can look like this:

    class SignatureMethod_HMAC_SHA256(SignatureMethod):
        name = 'HMAC-SHA256'
    
        def signing_base(self, request, consumer, token):
            if (not hasattr(request, 'normalized_url') or request.normalized_url is None):
                raise ValueError("Base URL for request is not set.")
    
            sig = (
                escape(request.method),
                escape(request.normalized_url),
                escape(request.get_normalized_parameters()),
            )
    
            key = '%s&' % escape(consumer.secret)
            if token:
                key += escape(token.secret)
            raw = '&'.join(sig)
            return key.encode('ascii'), raw.encode('ascii')
    
        def sign(self, request, consumer, token):
            """Builds the base signature string."""
            key, raw = self.signing_base(request, consumer, token)
    
            hashed = hmac.new(key, raw, sha256)
    
            # Calculate the digest base 64.
            return binascii.b2a_base64(hashed.digest())[:-1]
    

    Then you can simply call in your script new SHA256 method instead of that deprecated SHA1 method:

    signature_method = oauth.SignatureMethod_HMAC_SHA256()