SWIFT.文件签名问题的验证.64字节而不是71字节



我有一项任务要验证元数据的签名符合性,但由于某种原因,我使用的所有方法都返回"false"。文件通过C#以以下方式签名:

//Cert format X509Certificate2
var ecdsa = cert.GetECDsaPrivateKey());
byte[] signature;
signature = ecdsa.SignData(bufferedFileStream, HashAlgorithmName.SHA512);

我们得到的签名大小=64字节

但是swift原生方法生成大小=71字节的签名:

let signature = SecKeyCreateSignature(privateKey,
.ecdsaSignatureMessageX962SHA256,
fileData as CFData,
&signError)

ECDSA NIST p256生成的证书叹息。算法-ecdsa-with-SHA256

到目前为止,我尝试了3种检查方法:

//1
SecKeyVerifySignature(publicKey,
.ecdsaSignatureMessageX962SHA256,
fileData as CFData,
signature as! CFData,
&error)
//2
SecKeyRawVerify(publicKey,
.PKCS1SHA512,
hashedDataBytes,
digestLength,
signatureBytes,
signatureData.count)
//3
let publicKeyP265 = try! P256.Signing.PublicKey(x963Representation: bytesArray)
let ecdsaSignature = try! P256.Signing.ECDSASignature(rawRepresentation: signature)             
let result = publicKeyP265.isValidSignature(ecdsaSignature, for: fileData)

每种方法的结果均为阴性

到目前为止,我还未能成功验证签名,也许有人遇到了类似的问题。

使用ECDSA和P256时签名的大小与摘要的大小不同。ECDSA签名通常被编码为DER格式。您将有DER字节的开销以及额外的符号字节(无论整数是有符号的还是无符号的(。

下面我用python和密码库写了一个简单的例子。您可以看到签名的输出大小几乎总是70或更大。我还打印了DER签名的十六进制表示。

这里的散列大小很可能是不相关的。签名的最大区别与EC密钥的密钥大小有关。

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
message = b'Hello World'
for i in range(0, 10):
sig = ec.generate_private_key(ec.SECP256R1()).sign(message, ec.ECDSA(hashes.SHA512()))
print(f'{i}: {len(sig)} {sig.hex()}')
# 0: 71 30450221008466be7ca99fd80bc37527c078c30d07b725dd79feeb29816723259d27ccc367022051f1df8edbf82f528d587ce4db49e99b67cc6e8e61d83d90bfa050195c940721
# 1: 72 3046022100f478984dc0bccfb789713ab2ebb1636115ddaf55c7e8e44ba0c3b076e286def8022100a7ece3201a6cf521838a497510aede841bdc5ab2c59d225c2675a52b221419f6
# 2: 71 3045022100c6e8cfc1872f7aaa4d5c348bee5956ec7dc91422c07f382c402ac6d4265339f802206464c4e7d5d17b0bf28ba9b73cd16d4f1d59aa51d30144431a9367d3eb4fad78
# 3: 71 304502206ee73053a0479de84d1f5786705d121d9342bf1cc6d189fdfd30d55600e72b12022100efb16d5f5a4c7c1d60346e4c22395c955fa2abb2eb30f6649b1ee2c6921ac65a
# 4: 71 304502203a4f2ccec95a94b8b564a5abc837e39b33d338ad4c5ae421316644caac905722022100f78091452346154de97efdf7635c0c6bf74129e4868cd1c870f9b6ccbd20deac
# 5: 71 3045022100d960be8e6196de3e20098438783dfd8347163e5e78c631c592f1198ce3ffe1ef0220537a8e6efcbdcea3f15949c2896c88bd1b164474d34a367a33459e1db31b93d1
# 6: 72 3046022100a08a9e9cedec4341958b6690114a8e5569059e6c0bff3687acc3f49b53f3e105022100857932764645c8a195f4dd18820f12560be2ba2785fc745d49204aace2ebcfd8
# 7: 71 304502210087af13607c190d1656b0fc5d31b303f2616a92a7f516d5f528e8da59a61c0105022009094047f82158a6aca1b17ce6b276dc7122b7ecfebda7c517b6ab8770e40955
# 8: 71 3045022100885d72c1b31058f024d73d2a096cc662d847caf9db59b8483dd963fb70e6c3950220147ee83c980e2d866228c152e5c711817d3e60e60b7abff867ab9bd15b658777
# 9: 70 304402203eeb8b566a3198888bada3d346ab0caf7e14a882d1521120bee679209af2e4200220636100e9a6cd10386a9830a6c2885ee1fdfe00958473adb4bab1a85a0e3c8b11

因此,要回答您的问题,请使用DER格式设置签名:

var ecdsa = cert.GetECDsaPrivateKey();
byte[] signature;
signature = ecdsa.SignData(bufferedFileStream, HashAlgorithmName.SHA512, DSASignatureFormat.Rfc3279DerSequence);

您可以在此处找到该函数的文档,并在此处找到支持的格式。

我用下一个代码解决了我的问题:

let publicKeyP265 = try! P256.Signing.PublicKey(x963Representation: bytesArray)
let ecdsaSignature = try! P256.Signing.ECDSASignature(rawRepresentation: signature)
let fileDataDigest = SHA512.hash(data: fileData)

let result = publicKeyP265.isValidSignature(ecdsaSignature, for: fileDataDigest)

我希望它对其他人有用。

最新更新