Python hmac sha256 xác minh chữ ký

Tôi đang cố triển khai xác thực HMAC-SHA256 vào dự án API RESTful Python của mình. Tôi đang sử dụng Python Eve (được xây dựng trên Flask), bắt đầu bằng một ví dụ HMAC-SHA1 đơn giản hóa

Ứng dụng của tôi rất đơn giản

##
# application.py
##
from eve import Eve
from hmac import HMACAuth

SETTINGS = {
    'DEBUG': True,
    'MONGO_HOST': '127.0.0.1',
    'MONGO_PORT': 27017,
    'MONGO_DBNAME': 'testing',
    'DOMAIN': {'test': {}},
}

app = Eve(auth=HMACAuth, settings=SETTINGS)


if __name__ == '__main__':
    app.run(use_reloader=True)

và lớp HMACAuth

##
# hmac.py
##
import time
import hmac
from eve.auth import HMACAuth
from flask import current_app as app
from hashlib import sha256


class HMACAuth(HMACAuth):

    def check_auth(self, userid, hmac_hash, headers, data, allowed_roles, resource, method):
        # get user from database
        accounts = app.data.driver.db['accounts']
        user = accounts.find_one({'userid': userid})
        if user:
            # user found, we have its secret_key and we can re-create the signature user sent us
            check_sig = hmac.new(bytes(user['secret_key'], 'utf8'), b'', sha256)
            check_sig.update(bytes(headers['TIMESTAMP'], 'utf-8'))
            check_sig.update(data)
            check_signature = check_sig.hexdigest()

            # try to use python's hmac.compare_digest() to compare user's signature
            # and the one we re-created
            if hmac.compare_digest(check_signature, hmac_hash):
                # signature seems fine, we have to check if the request was sent in past 30 seconds
                # we are also checking for negative time because we have a test case with timestamp
                # in the future, so time_diff ends up with a negative number
                time_diff = int(time.time()) - int(headers['TIMESTAMP'])
                if 0 <= time_diff <= 30:
                    # everything seems superfine!
                    return True
                else:
                    # time_diff was either negative or more than 30
                    print('TIME ERROR ({}).'.format(time_diff))
            else:
                # hmac.compare_digest() failed!
                print('WRONG HASH!')
        else:
            # user doesn't even exist in our db
            print('USER DOES NOT EXIST.')

        # probably a mongodb related problem, should be properly wrapped in try/except block
        print('WAT?')
        return False

Tôi đã cố gắng viết một số bài kiểm tra cho ứng dụng này và cuối cùng tôi đã vượt qua tất cả chúng

##
# tests.py
##
import json
import unittest
import arrow
import base64
import hmac
from hashlib import sha256
from application import app


def prepare_test_request(
        test_user='testuser',
        test_user_secret='xxwMXEqOGiY2TssVZ9hvOB4x6EVW3RW75hjAKEai4UBlxG0ts8Js8dsWOzDvAVq4',
        seconds=0
):

    timestamp = arrow.utcnow().replace(seconds=+seconds)

    payload = {'testing': 'data'}
    payload_json = json.dumps(payload)
    payload_bytes = bytes(payload_json, 'utf-8')
    # is there any reason to send encoded payload to server or is json-formatted string just fine?
    payload_encoded = base64.urlsafe_b64encode(payload_bytes)  # not used at the moment

    sig = hmac.new(bytes(test_user_secret, 'utf-8'), b'', sha256)
    sig.update(bytes(str(timestamp.timestamp), 'utf-8'))
    sig.update(payload_bytes)
    signature = sig.hexdigest()

    headers = {
        'Authorization': '{}:{}'.format(test_user, signature),
        'timestamp': str(timestamp.timestamp),
    }
    return payload_bytes, headers


class BaseTest(unittest.TestCase):

    def setUp(self):
        app.config['TESTING'] = True
        self.app = app.test_client()

    def tearDown(self):
        pass

    def test_hmac(self):
        data, headers = prepare_test_request()  # plain request should return 200
        req = self.app.get('http://127.0.0.1:5000/', data=data, headers=headers)
        assert req.status_code == 200

    def test_hmac_30(self):
        data, headers = prepare_test_request(seconds=-30)  # 30 seconds ago should return 200
        req = self.app.get('http://127.0.0.1:5000/', data=data, headers=headers)
        assert req.status_code == 200

    def test_hmac_31(self):
        data, headers = prepare_test_request(seconds=-31)  # 31 seconds ago should return 401
        req = self.app.get('http://127.0.0.1:5000/', data=data, headers=headers)
        assert req.status_code == 401

    def test_hmac_future(self):
        data, headers = prepare_test_request(seconds=10)  # 10 seconds in the future should return 401
        req = self.app.get('http://127.0.0.1:5000/', data=data, headers=headers)
        assert req.status_code == 401

    def test_hmac_nonexisting_user(self):
        data, headers = prepare_test_request(test_user='nonexisting')
        req = self.app.get('http://127.0.0.1:5000/', data=data, headers=headers)
        assert req.status_code == 401

    def test_hmac_wrong_key(self):
        data, headers = prepare_test_request(test_user_secret='wrong!')
        req = self.app.get('http://127.0.0.1:5000/', data=data, headers=headers)
        assert req.status_code == 401

câu hỏi của tôi về điều này là

  • đây có phải là cách chính xác để xác thực người dùng bằng xác thực HMAC-SHA256 không?
  • như đã nêu trong tests.py, có cần phải mã hóa base64 payload và gửi theo cách đó đến máy chủ không? . ))
  • Tôi đã thử kiểm tra một vài trường hợp mà tôi nghĩ đến ban đầu, nhưng có điều gì khác mà tôi nên kiểm tra để chắc chắn rằng việc xác thực thực sự thực sự hiệu quả không?

Làm cách nào để tạo chữ ký HMAC SHA256 bằng Python?

Tạo hmac liên quan đến việc sử dụng khóa "riêng tư". Trong python, bạn có thể đạt được nó bằng hai thư viện hashlib và hmac. .
nhập hashlib
nhập khẩu hmac
khóa = '8oe0i89o7es243t5s234'
message = 'Nội dung cho hàm băm. ';
# Tạo hàm băm
chữ ký = hmac. Mới(
thông điệp,

Chữ ký HMAC SHA256 là gì?

HMAC-SHA256 là một thuật toán được xác định bởi RFC 2104 (RFC 2104—Băm theo khóa để xác thực thư) . Thuật toán lấy hai chuỗi byte làm đầu vào. một chìa khóa và một tin nhắn. Đầu ra của HMAC-SHA256 là một chuỗi byte, được gọi là thông báo. Bạn phải thực hiện mã hóa Base64 của thông báo này để tính chữ ký.

HMAC trong Python là gì?

Mã xác thực thông báo dựa trên hàm băm (hoặc HMAC) là công cụ để tính toán mã xác thực thông báo bằng cách sử dụng hàm băm mật mã kết hợp với khóa bí mật. You can use an HMAC to verify both the integrity and authenticity of a message.