【发布时间】:2021-12-17 14:48:38
【问题描述】:
我有一个 Python 后端,它生成公钥/私钥,生成一个有效负载,然后需要让该有效负载由客户端(ReactJS 或纯 JS)签名,稍后进行验证。
Python 中的实现如下所示:
进口
import json
import uuid
from backend.config import STARTING_BALANCE
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric.utils import (
encode_dss_signature,
decode_dss_signature
)
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives.serialization import load_pem_private_key
import base64
import hashlib
生成密钥:
class User:
def __init__(self):
self.address = hashlib.sha1(str(str(uuid.uuid4())[0:8]).encode("UTF-8")).hexdigest()
self.private_key = ec.generate_private_key(
ec.SECP256K1(),
default_backend()
)
self.private_key_return = self.private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
)
self.public_key = self.private_key.public_key()
self.serialize_public_key()
def serialize_public_key():
"""
Reset the public key to its serialized version.
"""
self.public_key = self.public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
).decode('utf-8')
签名:
def sign(self, data):
"""
Generate a signature based on the data using the local private key.
"""
return decode_dss_signature(self.private_key.sign(
json.dumps(data).encode('utf-8'),
ec.ECDSA(hashes.SHA256())
))
验证:
@staticmethod
def verify(public_key, data, signature):
"""
Verify a signature based on the original public key and data.
"""
deserialized_public_key = serialization.load_pem_public_key(
public_key.encode('utf-8'),
default_backend()
)
(r, s) = signature
try:
deserialized_public_key.verify(
encode_dss_signature(r, s),
json.dumps(data).encode('utf-8'),
ec.ECDSA(hashes.SHA256())
)
return True
except InvalidSignature:
return False
我现在需要的是在客户端加载(甚至生成)PEM 密钥,然后根据请求签署 JSON 有效负载,稍后可以从 Python 后端进行验证。
我尝试研究网络密码学和 cryptoJS 的用法,但没有成功。
我可以使用另一种更兼容的算法,但至少我需要签名功能完全正常工作。
我也尝试使用 Brython 和 Pyodide 将 Python 编译为 JS,但两者都无法支持所有必需的包。
简单来说,我正在寻找以下内容:
生成有效负载 (Python) -----> 签署有效负载 (JS) -----> 验证签名 (Python)
任何帮助/建议将不胜感激。
【问题讨论】:
-
在我的问题中,我简单地提到我尝试了这两种算法,并且我也愿意使用其他算法。我只是找不到任何有关在两种语言之间签名数据的文档。
-
考虑到我改用 secp256r1,您能否就上述内容提供任何指导? (似乎在 Python 中受支持,无需对代码进行任何重大更改)。
-
在这里您可以找到使用 WebCrypto/ECDSA 进行签名的示例:github.com/diafygi/webcrypto-examples#ecdsa---sign(以及其他示例,例如密钥生成或密钥导入/导出)。 WebCrypto 有点麻烦,所以如果您有问题,请发布您的代码并描述问题。如果 NodeJS 也是一种选择,NodeJS 的加密模块是另一种选择:nodejs.org/api/crypto.html#signsignprivatekey-outputencoding
-
一个选项可以是在浏览器端使用浏览器扩展。参考stackoverflow.com/a/68556286/9659885和stackoverflow.com/a/63173083/9659885
标签: javascript python cryptography cryptojs webcrypto-api