gpt4 book ai didi

python - 使用环验证 ECDSA 签名时出现“未指定”错误

转载 作者:行者123 更新时间:2023-12-03 11:46:28 33 4
gpt4 key购买 nike

在使用 ring 验证 ECDSA 签名时,我遇到了这个错误。箱。
我是一个最小的可复制示例,在 Python 中有一个工作版本。我可以验证输入字节(在解析证书等之后)在两者中完全相同。

import base64

try:
import ecdsa.util
from cryptography import x509
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec as cryptography_ec
from cryptography.hazmat.primitives.asymmetric.utils import encode_dss_signature
from cryptography.hazmat.primitives.hashes import SHA384
except ImportError:
print("Missing deps, install:\n\n\tpip install ecdsa cryptography")


CERT = """-----BEGIN CERTIFICATE-----
MIIDBjCCAougAwIBAgIIFiJLFfdxFlYwCgYIKoZIzj0EAwMwgaMxCzAJBgNVBAYT
AlVTMRwwGgYDVQQKExNNb3ppbGxhIENvcnBvcmF0aW9uMS8wLQYDVQQLEyZNb3pp
bGxhIEFNTyBQcm9kdWN0aW9uIFNpZ25pbmcgU2VydmljZTFFMEMGA1UEAww8Q29u
dGVudCBTaWduaW5nIEludGVybWVkaWF0ZS9lbWFpbEFkZHJlc3M9Zm94c2VjQG1v
emlsbGEuY29tMB4XDTIwMDYxNjE3MTYxNVoXDTIwMDkwNDE3MTYxNVowgakxCzAJ
BgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFp
biBWaWV3MRwwGgYDVQQKExNNb3ppbGxhIENvcnBvcmF0aW9uMRcwFQYDVQQLEw5D
bG91ZCBTZXJ2aWNlczE2MDQGA1UEAxMtcmVtb3RlLXNldHRpbmdzLmNvbnRlbnQt
c2lnbmF0dXJlLm1vemlsbGEub3JnMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEDmOX
N5IGlUqCvu6xkOKr020Eo3kY2uPdJO0ZihVUoglk1ktQPss184OajFOMKm/BJX4W
IsZUzQoRL8NgGfZDwBjT95Q87lhOWEWs5AU/nMXIYwDp7rpUPaUqw0QLMikdo4GD
MIGAMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAfBgNVHSME
GDAWgBSgHUoXT4zCKzVF8WPx2nBwp8744TA4BgNVHREEMTAvgi1yZW1vdGUtc2V0
dGluZ3MuY29udGVudC1zaWduYXR1cmUubW96aWxsYS5vcmcwCgYIKoZIzj0EAwMD
aQAwZgIxAJvyynyPqRmRMqf95FPH5xfcoT3jb/2LOkUifGDtjtZ338ScpT2glUK8
HszKVANqXQIxAIygMaeTiD9figEusmHMthBdFoIoHk31x4MHukAy+TWZ863X6/V2
6/ZrZMp6Wq/0ow==
-----END CERTIFICATE-----
"""

SIG = "oPRadsg_5wnnUXlRIjamXKPWyyGe4VLt-KR4-PJTK2hq4hF196L3nbvne1_7-HfpoVRR4BLsHWtnnt6700CTt5kNgwvrE8aJ3nXFa0vJBoOvIRco-vCt-rJ7acEu0IFG"

DATA = b"""Content-Signature:\x00{"data":[],"last_modified":"1594998798350"}"""

# Parse X509 certificate
cert = x509.load_pem_x509_certificate(CERT.encode("utf8"), backend=default_backend())


signature = base64.urlsafe_b64decode(SIG)
r, s = ecdsa.util.sigdecode_string(
signature, order=ecdsa.curves.NIST384p.order
)
signature_dss = encode_dss_signature(r, s)

algorithm = cryptography_ec.ECDSA(SHA384())

cert.public_key().verify(signature_dss, DATA, algorithm)

print("SUCCESS!")
print("PK:\t", cert.public_key().public_bytes(encoding=serialization.Encoding.X962, format=serialization.PublicFormat.UncompressedPoint).hex())
print("Sig:\t", signature.hex())
print("Data:\t", DATA.hex())

ring (和 x509-parser ),它看起来像这样以及对 verify() 的调用失败 Unspecified错误,这不是很有帮助( ring API docs):
use base64;
use ring::signature;
use x509_parser;

const CERTIFICATE: &str = r#"-----BEGIN CERTIFICATE-----
MIIDBjCCAougAwIBAgIIFiJLFfdxFlYwCgYIKoZIzj0EAwMwgaMxCzAJBgNVBAYT
AlVTMRwwGgYDVQQKExNNb3ppbGxhIENvcnBvcmF0aW9uMS8wLQYDVQQLEyZNb3pp
bGxhIEFNTyBQcm9kdWN0aW9uIFNpZ25pbmcgU2VydmljZTFFMEMGA1UEAww8Q29u
dGVudCBTaWduaW5nIEludGVybWVkaWF0ZS9lbWFpbEFkZHJlc3M9Zm94c2VjQG1v
emlsbGEuY29tMB4XDTIwMDYxNjE3MTYxNVoXDTIwMDkwNDE3MTYxNVowgakxCzAJ
BgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFp
biBWaWV3MRwwGgYDVQQKExNNb3ppbGxhIENvcnBvcmF0aW9uMRcwFQYDVQQLEw5D
bG91ZCBTZXJ2aWNlczE2MDQGA1UEAxMtcmVtb3RlLXNldHRpbmdzLmNvbnRlbnQt
c2lnbmF0dXJlLm1vemlsbGEub3JnMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEDmOX
N5IGlUqCvu6xkOKr020Eo3kY2uPdJO0ZihVUoglk1ktQPss184OajFOMKm/BJX4W
IsZUzQoRL8NgGfZDwBjT95Q87lhOWEWs5AU/nMXIYwDp7rpUPaUqw0QLMikdo4GD
MIGAMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzAfBgNVHSME
GDAWgBSgHUoXT4zCKzVF8WPx2nBwp8744TA4BgNVHREEMTAvgi1yZW1vdGUtc2V0
dGluZ3MuY29udGVudC1zaWduYXR1cmUubW96aWxsYS5vcmcwCgYIKoZIzj0EAwMD
aQAwZgIxAJvyynyPqRmRMqf95FPH5xfcoT3jb/2LOkUifGDtjtZ338ScpT2glUK8
HszKVANqXQIxAIygMaeTiD9figEusmHMthBdFoIoHk31x4MHukAy+TWZ863X6/V2
6/ZrZMp6Wq/0ow==
-----END CERTIFICATE-----"#;

const SIGNATURE: &str = r#"oPRadsg_5wnnUXlRIjamXKPWyyGe4VLt-KR4-PJTK2hq4hF196L3nbvne1_7-HfpoVRR4BLsHWtnnt6700CTt5kNgwvrE8aJ3nXFa0vJBoOvIRco-vCt-rJ7acEu0IFG"#;

const DATA: &str = r#"Content-Signature:\x00{"data":[],"last_modified":"1594998798350"}"#;

macro_rules! hex {
($b: expr) => {
{
let ss: Vec<String> = $b.iter()
.map(|b| format!("{:02x}", b))
.collect();
ss.join("")
}
};
}

fn main() {
let pem = match x509_parser::pem::parse_x509_pem(CERTIFICATE.as_bytes()) {
Ok((rem, pem)) => {
assert!(rem.is_empty());
//
assert_eq!(pem.label, String::from("CERTIFICATE"));
//
pem
},
err => panic!("PEM parsing failed: {:?}", err),
};

let x509 = match x509_parser::parse_x509_certificate(&pem.contents) {
Ok((rem, x509)) => {
assert!(rem.is_empty());
x509
},
err => panic!("X509 parsing failed: {:?}", err),
};

let spki = x509.tbs_certificate.subject_pki;
let public_key = signature::UnparsedPublicKey::new(
&signature::ECDSA_P384_SHA384_ASN1,
&spki.subject_public_key.data,
);

let signature_bytes = base64::decode_config(&SIGNATURE, base64::URL_SAFE).unwrap();

println!("PK:\t{}", hex!(spki.subject_public_key.data));
println!("Sig:\t{}", hex!(signature_bytes));
println!("Data:\t{}", hex!(DATA.as_bytes()));

match public_key.verify(&DATA.as_bytes(), &signature_bytes) {
Ok(_) => (),
Err(err) => println!("ERROR {:?}", err),
}
}

使用 openssl x509 -inform PEM -in cert.pem -text我还可以确保公钥是 ASN1,并且字节也匹配。
我错过了什么明显的东西吗?
我该怎么做才能对错误有更多的了解?
谢谢!

最佳答案

我想到了。
首先,在 python 示例中,打印的签名不是传递给 verify() 的签名。 .应该是 print("Sig:\t", signature_dss.hex()) .
其次,在 Rust 中,Content-Signature:\x00部分不应是 DATA 中的原始字符串.可能是 let payload = format!("Content-Signature:\x00{}", r#"{"data":[],"last_modified":"1594998798350"}"#);例如。
最后,最重要的是,我们也必须在 Rust 中将签名点值编码为 DER(在 Python 端相当于 encode_dss_signature())。由于der_writer模块 is not publicring ,我最终实现了一个快速的特定的:

use ring::io::der;

fn encode_dss_signature(signature_bytes: Vec<u8>) -> Vec<u8> {
// Split the signature in two integers (48 bytes each)
let sig_len = signature_bytes.len();
let r_bytes = &signature_bytes[0..sig_len / 2];
let s_bytes = &signature_bytes[sig_len / 2..];

// Encode the two integer points.
// See https://github.com/briansmith/ring/blob/3b1ece4/src/io/der_writer.rs
let mut tuple_der: Vec<u8> = Vec::new();
for val in [r_bytes, s_bytes].iter() {
tuple_der.push(der::Tag::Integer as u8);
tuple_der.push((val.len() + 1) as u8);
if (val[0] & 0x80) != 0 {
// Disambiguate negative number.
tuple_der.push(0x00);
}
tuple_der.extend(*val);
}

// Sequence tag followed by content length and bytes.
let mut signature_der: Vec<u8> = Vec::new();
signature_der.push(der::Tag::Sequence as u8);
signature_der.push(tuple_der.len() as u8);
signature_der.extend(tuple_der);

signature_der
}
现在可以成功验证签名!

关于python - 使用环验证 ECDSA 签名时出现“未指定”错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66492119/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com