Search code examples
swifthashopensslrsaasn.1

OpenSSL RSA public key digest


I'm trying to calculate the hash over a public key on both iOS (Swift) and macOS (terminal & OpenSSL), but both platforms export the key in a slightly different format.

My Swift code extracts the sequence containing both the modulus and exponent (according to Apple this is the PKCS#1 container).

let export = SecKeyCopyExternalRepresentation(publicKey, nil)! as Data
let hash = SHA256.hash(data: export)
// SHA256 digest: 57fc8238c609045b7c0b546f58d5f797ebec4e39eff481459edfb67bd850834d
print(hash)

Now when I do similar things with the terminal I get a different output.

openssl rsa -pubin -outform DER | openssl dgst -sha256                             
# writing RSA key
# 0ee9c99ef4ca3316e90dde23925bc9a670fa309d6f4663bb5d42050b5089b086

The latter one is cause by OpenSSL wrapping the output in a fuller structured ASN.1 container.

SEQUENCE      (ASN.1 container)
  SEQUENCE
    OID       (RSA algorithm)
    NULL
  BITSTRING
    SEQUENCE  (iOS container)   
      INTEGER (Modulus)
      INTEGER (Exponent)

How can I use OpenSSL to export the key into only the sequence iOS expects, so the has will be the same for both commands?


Solution

  • It turns out OpenSSL has an undocumented parameter -RSAPublicKey_out that outputs the same data that SecKeyCopyExternalRepresentation does.

    openssl rsa -pubin -RSAPublicKey_out -outform DER | openssl dgst -sha256
    

    This provides the same digest for both iOS and macOS