LINUX.ORG.RU

Генерация подписи (Ruby -> Python)

 ,


1

2

Всем привет, подаказите как вот такой код портировать на python:

  def self.valid_callback?(signature:, request_uri:, secret:)
    signature == self.signature(nonce: nil, body: nil, method: 'GET', request_uri: request_uri, secret: secret)
  end

  def self.signature(nonce:, body:, method:, request_uri:, secret:)
    sha512  = OpenSSL::Digest::SHA512.new
    request = "#{method.to_s.upcase}#{request_uri}#{sha512.digest("#{nonce}#{body}")}"
    Base64.strict_encode64 OpenSSL::HMAC.digest(sha512, secret.to_s, request)
  end

Вроде бы все сделал как надо, но подписи не совпадают, вот мой код:

def generate_signature(request_uri, secret):
    method = 'GET'
    sha512 = hashlib.sha512()
    sha512.update("".encode("utf-8"))
    request = str(method).upper()+request_uri+str(sha512.hexdigest())
    hmac = hashlib.pbkdf2_hmac('sha512', bytes(secret.encode("utf-8")), bytes(request.encode("utf-8")), 100000)
    hexhmac = binascii.hexlify(hmac)
    
    return base64.b64encode(hmac)

★★★

Ответ на: комментарий от pi11

я думаю надо было не pbkdf2_hmac брать а hmac, сейчас попробую.

Int64 ★★★
() автор топика
Ответ на: комментарий от pi11

Можно, просто эта сигнатура приходит с другого сервиса, и нужно проверить валидность это подписи, чтобы проверить в документации написано нужно таким образом сгенерировать подпись и сравнить, но они почему-то не равны...

Int64 ★★★
() автор топика
Ответ на: комментарий от Int64

Ну ты для начала проверь что строки request равны.

pi11 ★★★★★
()

Какой Python?

Вот это выбрось sha512.update("".encode("utf-8")).

In: hashlib.sha512(b'').hexdigest() == hashlib.sha512().hexdigest()
Out: True
Ибо оно уже проинициализировано.

Дальше request - тихий ужас :(
Т.к. type(hashlib.sha512().hexdigest()) == str и method тоже строка.

request = '{}{}{}'.format(method.upper(), request_uri, sha512.hexdigest())

Далее функция bytes имеет второй параметр encoding Т.е. можно вот эту срань bytes(secret.encode("utf-8")) упростить до bytes(secret, 'UTF-8'))

P.S. код не проверял свой, но на 95% он рабочий.
Если что, спрашивай.

deterok ★★★★★
()
Последнее исправление: deterok (всего исправлений: 2)

подписи не совпадают

Не удивительно. Два совершенно разных метода. В одном — digest("#{nonce}#{body}") и HMAC, в другом — hexdigest() без данных и PKCS5.

Кстати в Руби есть Digest::SHA512.base64digest.

from hashlib import sha512
from hmac import HMAC
from base64 import b64encode

def generate_signature(uri, secret, nonce='', body='', method='GET'):
    bindata = (nonce + body).encode()
    digest  = sha512(bindata).digest()
    message = (method + uri).encode() + digest
    secret  = secret.encode()
    
    h = HMAC(secret, message, 'sha512')
    #~ hmachex = h.hexdigest()
    hmacb64 = b64encode(h.digest())

    return hmacb64
    
sig = generate_signature('do', 'you', 'speak', 'inglich')
print(sig)
# b'zIdd4icESK0jilfMCda8uJQftjhUwyet7KKdlkr8y00OXqp9hNT+Rb3jI3b68sg8tcZdFDLXJ0tZ5GG/nOGFrg=='

sig = generate_signature('da', 'konechno')
print(sig)
# b'teNFH3DeyfgBomUDt8PVor+eDd1eM/sHzGR4dbA7t1crRoIsL/b+c6c06VXCQKT7Pgn78flHQhT4e643bGhcCQ=='

Чувствуешь разницу?

anonymous
()
Ответ на: комментарий от deterok

Спасибо за полезные пояснения :)

Int64 ★★★
() автор топика
Ответ на: комментарий от anonymous

Разницу чувствую, но все равно подписи не совпадают к сожалению :(

Int64 ★★★
() автор топика
Ответ на: комментарий от anonymous

Пойду писать в тех поддержку...
По документации по сути то же самое вроде делаю:
https://admin.gear.mycelium.com/docs/api/signed_request
Может немного не совпадает request_uri его я получаю так: request.get_full_path() (Django)
ну и у меня сомнения на счет gateway_secret, потому-что там есть только API Gateway ID, ну я и подумал что это одно и тоже, тем более что длина строки совпадает.

Int64 ★★★
() автор топика
Последнее исправление: Int64 (всего исправлений: 2)
Ответ на: комментарий от Int64

А почему ты решил, что подписи должны совапдать?

Кроме блока, ключей, хэша и криптоалгоритма функция генерации подписи может использовать случайную «соль» («нонсенс»), время создания подписи и т.д. Поэтому для одного и того же блока подписи, созданные в разное время, бинарно могут отличаться.

Если ты хочешь проверить валидность (корректность) подписи, то надо использовать функцию verify.

Novator ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.