我正在使用 Python Cryptography 和 Nodejs Crypto 库。我希望在 Python 中对签名进行数字签名并在 Nodejs 中进行验证。
示例密钥对:从 Hashicorp Vault 获得(类型:ecdsa-p521)
PRIVATE_KEY="-----BEGIN EC PRIVATE KEY-----\nMIHcAgEBBEIB1ZsDtu9EeMUma3p0M4jWrA4jJrBirDyhLfATvXVMWNDmrH5EX49T\ndOzAsKq92IXi2g1HtdIaYBBTde5lkBNfUK+gBwYFK4EEACOhgYkDgYYABAESgmpD\nCcElrFK/HPwJaNUkSly25hcQe0KnSFoIIlIBVba5jPxz2erUDIPr34RINUb3LS7j\n5MxELHl/VINKFdNhzgGJT4IWzL9VR6p8auN4+DNy7lLr4veBvB3yY87MkfaRWqlB\nyjpMre0vudtOAHUbZ6F6l4BPBPIAQaYHHiuNWSrjlg==\n-----END EC PRIVATE KEY-----"
PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\nMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBEoJqQwnBJaxSvxz8CWjVJEpctuYXEHtCp0haCCJSAVW2uYz8c9nq1AyD69+ESDVG9y0u4+TMRCx5f1SDShXTYc4BiU+CFsy/VUeqfGrjePgzcu5S6+L3gbwd8mPOzJH2kVqpQco6TK3tL7nbTgB1G2ehepeATwTyAEGmBx4rjVkq45Y=\n-----END PUBLIC KEY-----"
蟒蛇
import base64
from os import urandom
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec, utils
from cryptography.hazmat.primitives.serialization import (
load_pem_private_key,
load_pem_public_key,
)
from cryptography.hazmat.backends import default_backend
from cryptography.exceptions import InvalidSignature
def sign() -> "dict[str, str]":
# ecdsa signing
privKey = load_pem_private_key(
PRIVATE_KEY.encode(),
password=None,
backend=default_backend,
)
msg = urandom(12)
chosen_hash = hashes.SHA256()
hasher = hashes.Hash(chosen_hash, backend=default_backend)
hasher.update(msg)
digest = hasher.finalize()
signature = privKey.sign(
digest,
ec.ECDSA(utils.Prehashed(chosen_hash)),
)
return {
"msg": base64.b64encode(msg).decode(),
"sign": base64.b64encode(signature).decode(),
}
def verify(signObj: "dict[str, str]") -> bool:
pubKey = load_pem_public_key(
PUBLIC_KEY.encode(),
backend=default_backend,
)
try:
pubKey.verify(
base64.b64decode(signObj["sign"].encode()),
base64.b64decode(signObj["msg"].encode()),
ec.ECDSA(hashes.SHA256()),
)
except InvalidSignature:
return False
return True
if __name__ == "__main__":
res = sign()
print(res)
print(verify(res))
就其本身而言,签名和验证工作。
打字稿:
import * as crypto from "crypto";
const algo = "sha256";
const base64 = "base64";
class SignObj {
readonly msg: string;
readonly sign: string;
constructor(msg: string, sign: string) {
this.msg = msg;
this.sign = sign;
}
}
function sign(): SignObj {
const msg = crypto.randomBytes(12);
const hash = crypto.createHash(algo).update(msg).end();
const hashDigest = hash.digest();
const signer = crypto.createSign(algo);
signer.write(hashDigest);
signer.end();
const sign = signer.sign(PRIVATE_KEY, base64);
return new SignObj(msg.toString(base64), sign);
}
function verify(signObj: SignObj): boolean {
const hash = crypto
.createHash(algo)
.update(Buffer.from(signObj.msg, base64))
.end();
const hashDigest = hash.digest();
const verifier = crypto.createVerify(algo);
verifier.write(hashDigest);
verifier.end();
return verifier.verify(PUBLIC_KEY, Buffer.from(signObj.sign, base64));
}
console.log(verify(sign()));
再次,签名和验证本身就有效。
但是如果我们手动提取值,例如,从 Python 到 Typescript 的结果
{
'msg': 'Oz4ZRvzcTRs7CEKV',
'sign': 'MIGGAkEkbIqN8uPwzMf50NiqXKuSdT4c+8Lchz7o5eKPfiPp3jMDtW1TqQseCJw7/8mIcvTRdYeFlYsf58vFbxkk/jpi/QJBBkw9MKelCXcEPecM5/5HqJrkD2XijtNgj7AKzsMTv/Y7721S6hnb48sBKj6DTQ9Dfnsf1uPZNb4KIa7KhwX5ebw='
}
放入打字稿
const res = new SignObj(
"Oz4ZRvzcTRs7CEKV",
"MIGGAkEkbIqN8uPwzMf50NiqXKuSdT4c+8Lchz7o5eKPfiPp3jMDtW1TqQseCJw7/8mIcvTRdYeFlYsf58vFbxkk/jpi/QJBBkw9MKelCXcEPecM5/5HqJrkD2XijtNgj7AKzsMTv/Y7721S6hnb48sBKj6DTQ9Dfnsf1uPZNb4KIa7KhwX5ebw="
);
console.log(res);
console.log(verify(res)); // --> False
不太确定出了什么问题。任何帮助都会有所帮助。提前谢谢~