2

On iOS I am generating a pair of private and public key with the following code:

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())

From the code I got:

private key: b02f6fd1c1a9986f0e8cc84cd84a5061e46582e9620981d6dadbc0d503c2be4f
public key: 043fbd15edf44c644e2cdaba55db35170521e5c4bd09156b4930cc5721d64be694191e32f33b7a0b583ca301bd76fb2f93df774eddac72add74ef938d236ad1673

DER signature: 304502200ded05de61c062e9b8c5a3af9b18cdb05bd8d19597494869c150d00f490a3a30022100cf1ca3c6a9c8c1f5fb32e8d101179f64c49f9d69d3043dcd2371fff9a5dd74b3
base64 DER signature: MEUCIA3tBd5hwGLpuMWjr5sYzbBb2NGVl0lIacFQ0A9JCjowAiEAzxyjxqnIwfX7MujRARefZMSfnWnTBD3NI3H/+aXddLM=

I tried to verify the DER signature with the keys through the tool here, which the site determined that the signature is valid.

However, if I try to verify the same result with the following Ruby code using OpenSSL:

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)

The signature is determined to be invalid:

irb(main):074:0> key.dsa_verify_asn1(data, signature)
=> false

I am thinking it is probably due to some format issues of the signature but I don't have any idea or direction to look for. Is this the case? Or did I miss something else?

Topaco
  • 40,594
  • 4
  • 35
  • 62
peakingcube
  • 1,388
  • 15
  • 32

1 Answers1

1

The Ruby code does not hash the data implicitly, meaning that this must be done explicitly:

...
dataHash = OpenSSL::Digest::SHA256.digest(data)
verified = key.dsa_verify_asn1(dataHash, signature)
print verified # true

With this fix, the verification with the Ruby code is successful.

Topaco
  • 40,594
  • 4
  • 35
  • 62