Using Base64 encoded Public Key to verify RSA signature

jscheppers picture jscheppers · Feb 14, 2012 · Viewed 23.2k times · Source

In a nutshell, this is my problem:

private string publicKeyString = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVGUzbydMZS+fnkGTsUkDKEyFOGwghR234d5GjPnMIC0RFtXtw2tdcNM8I9Qk+h6fnPHiA7r27iHBfdxTP3oegQJWpbY2RMwSmOs02eQqpKx4QtIjWqkKk2Gmck5cll9GCoI8AUAA5e0D02T0ZgINDmo5yGPhGAAmqYrm8YiupwQIDAQAB";

/* Some transformation required, using publicKeyString to initiate a new RSACryptoServiceProvider object
*/

//for now:
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

byte[] selfComputedHash = new byte[]; //left out of the example
byte[] signature = new byte[];

bool result = rsa.VerifyHash(selfComputedHash, CryptoConfig.MapNameToOID("SHA1"), signature);

As you can see, the problem is initiating a new RSACryptoServiceProvider with the given Base64 encoded public key string. I've been able to do the instantiation using an object RSAParameters, loaded with the byte[]'s for Modulus and Exponent derived from this public key string using an OpenSSL shell command. But since this public key may change in the future I want to be able to store it in its original form in a database. There must be a more straightforward way of dealing with this.

A lot of the examples I've read so far avoid this problem by exporting and importing the generated private and public keys to and from a key-container object and use it in the same piece of code and thus not 'transferring' the key in some string form out of memory. Some people have expressed the same problem, both here on StackOverflow and on other sites, but I have not been able to find a satisfying answer yet.

Any idea's are more than welcome.

Background info: My communication partner computes a 20-byte SHA1-hash from an input string of variable length, composed of the information contained in several fields of an ASCII encoded message. This hash is then RSA-signed with my partner's private key and sent along with the ASCII message to me. Upon arrival, I compute the SHA1 hash myself, using the same fields from the ASCII message and then try to verify if these fields were not altered by calling VerifyHash.

The key is provided in 2 forms: regular and 'noNL'. The noNL version is included in the code above, the regular version is this:

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVGUzbydMZS+fnkGTsUkDKEyFO
GwghR234d5GjPnMIC0RFtXtw2tdcNM8I9Qk+h6fnPHiA7r27iHBfdxTP3oegQJWp
bY2RMwSmOs02eQqpKx4QtIjWqkKk2Gmck5cll9GCoI8AUAA5e0D02T0ZgINDmo5y
GPhGAAmqYrm8YiupwQIDAQAB
-----END PUBLIC KEY-----

Answer

Rasmus Faber picture Rasmus Faber · Feb 15, 2012

Your string is the base64 encoding of a SubjectPublicKeyInfo. You can use Bouncycastle.net to decode it like this:

byte[] publicKeyBytes = Convert.FromBase64String(publicKeyString);
AsymmetricKeyParameter asymmetricKeyParameter = PublicKeyFactory.CreateKey(publicKeyBytes);
RsaKeyParameters rsaKeyParameters = (RsaKeyParameters) asymmetricKeyParameter;
RSAParameters rsaParameters = new RSAParameters();
rsaParameters.Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned();
rsaParameters.Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned();
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(rsaParameters);