This code relates to DKIM signature verification used in anti-spam efforts.
I have a byte[]
from s1024._domainkey.yahoo.com
that is ASN.1 encoded, but I don't know if that alone contains enough information to materialize a public key.
Based on this class, it appears I can convert an ASN.1 key into a X509Certificate Public key, but I need to supply an OID and some ASN.1-encoded parameters.
In this example I have metadata that the ASN1 key is:
- An RSA encoded key (ASN.1 DER-encoded [ITU-X660-1997] RSAPublicKey per RFC3447)
- Used with either sha1 sha256 hash algorithms
- Uses an OID relating to the following table from section A.2 of RFC3447 (though I don't know how to turn this information into a full OID)
/*
* 1.2.840.113549.1
*
MD2 md2WithRSAEncryption ::= {pkcs-1 2}
MD5 md5WithRSAEncryption ::= {pkcs-1 4}
SHA-1 sha1WithRSAEncryption ::= {pkcs-1 5}
SHA-256 sha256WithRSAEncryption ::= {pkcs-1 11}
SHA-384 sha384WithRSAEncryption ::= {pkcs-1 12}
SHA-512 sha512WithRSAEncryption ::= {pkcs-1 13}
*/
Code sample
string pubkey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrEee0Ri4Juz+QfiWYui/E9UGSXau/2P8LjnTD8V4Unn+2FAZVGE3kL23bzeoULYv4PeleB3gfmJiDJOKU3Ns5L4KJAUUHjFwDebt0NP+sBK0VKeTATL2Yr/S3bT/xhy+1xtj4RkdV7fVxTn56Lb4udUnwuxK4V5b5PdOKj/+XcwIDAQAB";
byte[] pubkeyByteArray = Convert.FromBase64String(pubkey);
AsnEncodedData aData = new AsnEncodedData(pubkeyByteArray);
// OID must not be null, but it is here. What is it?
System.Security.Cryptography.X509Certificates.PublicKey pubKeyRdr = new System.Security.Cryptography.X509Certificates.PublicKey(aData.Oid, null, aData);
Question
- What OID should I use?
- What are examples of ASN.1 parameters?
Update
This is the data you have provided when it is parsed using the link @erickson provided:
SEQUENCE (2 elem)
SEQUENCE (2 elem)
OBJECT IDENTIFIER 1.2.840.113549.1.1.1
NULL
BIT STRING (1 elem)
SEQUENCE (2 elem)
INTEGER(1024 bit)
INTEGER 65537
The reason the previous code throws a ASN1 bad tag value met.
exception is because aData
contains incorrect data (contains all the data above). From what I've seen, the is how the 3 arguments to System.Security.Cryptography.X509Certificates.PublicKey
are broken down.
- The first parameter is the OID, which is the OBJECT IDENTIFIER above.
- The second parameter is the public key parameters. In the parsing above, you can see it is NULL.
- The third parameter is actual public key value. This is made up of the third sequence above. The sequence has 2 integers, a 1024-bit modulus followed by the public exponent.
I tested it using the code below. I couldn't find a built-in method to parse the data without writing a DER parser.
Oid oid = new Oid("1.2.840.113549.1.1.1");
AsnEncodedData keyValue = new AsnEncodedData(getBytes("30818902818100EB11E7B4462E09BB3F907E2598BA2FC4F541925DABBFD8FF0B8E74C3F15E149E7FB6140655184DE42F6DDBCDEA142D8BF83DE95E07781F98988324E294DCDB392F82890145078C5C0379BB7434FFAC04AD1529E4C04CBD98AFF4B76D3FF1872FB5C6D8F8464755EDF5714E7E7A2DBE2E7549F0BB12B85796F93DD38A8FFF97730203010001"));
AsnEncodedData keyParam = new AsnEncodedData(new byte[] {05, 00});
PublicKey pubKeyRdr = new System.Security.Cryptography.X509Certificates.PublicKey(oid, keyParam, keyValue);
System.Diagnostics.Debug.WriteLine(pubKeyRdr.Key.KeyExchangeAlgorithm);
System.Diagnostics.Debug.WriteLine(pubKeyRdr.Key.KeySize);
It outputs RSA-PKCS1-KeyEx
and 1024
.
What you have is a SubjectPublicKeyInfo structure. It looks like this:
Sequence {
Sequence {
Oid: 1.2.840.113549.1.1.1
Parameters: null
}
KeyValue: blah blah
}
The oid for RSA keys is 1.2.840.113549.1.1.1.
For an RSA key, there are no parameters, so this is null.
However, I don't see any API on AsnEncodedData
to parse apart the elements and get at what you need.