在iOS上,我使用以下代码生成一对私钥和公钥:
extension Data {
var hexString: String {
return map { String(format: "%02hhx", $0) }.joined()
}
}
let privateKey = P256.Signing.PrivateKey()
let publicKey = privateKey.publicKey
print("private key: " + privateKey.rawRepresentation.hexString)
print("public key: " + "04" + publicKey.rawRepresentation.hexString)
let message = "A message to sign"
let signature = try! privateKey.signature(for: message.data(using: .utf8)!)
print("DER signature: " + signature.derRepresentation.hexString)
print("base64 DER signature: " + signature.derRepresentation.base64EncodedString())
从代码中我得到:
private key: b02f6fd1c1a9986f0e8cc84cd84a5061e46582e9620981d6dadbc0d503c2be4f
public key: 043fbd15edf44c644e2cdaba55db35170521e5c4bd09156b4930cc5721d64be694191e32f33b7a0b583ca301bd76fb2f93df774eddac72add74ef938d236ad1673
DER signature: 304502200ded05de61c062e9b8c5a3af9b18cdb05bd8d19597494869c150d00f490a3a30022100cf1ca3c6a9c8c1f5fb32e8d101179f64c49f9d69d3043dcd2371fff9a5dd74b3
base64 DER signature: MEUCIA3tBd5hwGLpuMWjr5sYzbBb2NGVl0lIacFQ0A9JCjowAiEAzxyjxqnIwfX7MujRARefZMSfnWnTBD3NI3H/+aXddLM=
我试图通过这里的工具用密钥验证DER签名,该网站确定签名有效。
但是,如果我尝试使用OpenSSL使用以下Ruby代码验证相同的结果:
group = OpenSSL::PKey::EC::Group.new('prime256v1')
key = OpenSSL::PKey::EC.new(group)
public_key_hex = '043fbd15edf44c644e2cdaba55db35170521e5c4bd09156b4930cc5721d64be694191e32f33b7a0b583ca301bd76fb2f93df774eddac72add74ef938d236ad1673'
public_key_bn = OpenSSL::BN.new(public_key_hex, 16)
public_key = OpenSSL::PKey::EC::Point.new(group, public_key_bn)
key.public_key = public_key
data = 'A message to sign'
signature_base64 = 'MEUCIA3tBd5hwGLpuMWjr5sYzbBb2NGVl0lIacFQ0A9JCjowAiEAzxyjxqnIwfX7MujRARefZMSfnWnTBD3NI3H/+aXddLM='
signature = Base64.decode64(signature_base64)
key.dsa_verify_asn1(data, signature)
签名被确定为无效:
irb(main):074:0> key.dsa_verify_asn1(data, signature)
=> false
我想这可能是由于签名的一些格式问题,但我没有任何想法或方向去寻找。是这样吗?还是我错过了什么?
Ruby代码不会隐式地散列数据,这意味着必须显式地完成:
...
dataHash = OpenSSL::Digest::SHA256.digest(data)
verified = key.dsa_verify_asn1(dataHash, signature)
print verified # true
通过这个修复,Ruby代码的验证是成功的。