c# symmetric encryption
Uso de la clave pública codificada en Base64 para verificar la firma RSA (3)
En pocas palabras, este es mi problema:
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);
Como puede ver, el problema es iniciar un nuevo RSACryptoServiceProvider con la cadena de clave pública codificada en Base64. He podido realizar la creación de instancias utilizando un objeto RSAParameters, cargado con el byte [] para Módulo y Exponente derivado de esta cadena de clave pública usando un comando de shell OpenSSL. Pero como esta clave pública puede cambiar en el futuro, quiero poder almacenarla en su forma original en una base de datos. Debe haber una manera más directa de lidiar con esto.
Muchos de los ejemplos que he leído hasta ahora evitan este problema exportando e importando las claves privadas y públicas generadas desde y hacia un objeto de contenedor de claves y lo utilizan en el mismo fragmento de código y, por lo tanto, no "transfieren" la clave a algunas cadenas se forman fuera de la memoria. Algunas personas han expresado el mismo problema, tanto aquí en StackOverflow como en otros sitios, pero aún no he podido encontrar una respuesta satisfactoria.
Cualquier idea es más que bienvenida.
Información de fondo: Mi compañero de comunicación calcula un hash SHA1 de 20 bytes a partir de una cadena de entrada de longitud variable, compuesta por la información contenida en varios campos de un mensaje codificado en ASCII. Este hash es luego firmado por RSA con la clave privada de mi compañero y se me envía junto con el mensaje ASCII. Al llegar, calculo el hash SHA1 por mí mismo, usando los mismos campos del mensaje ASCII y luego trato de verificar si estos campos no se modificaron llamando a VerifyHash.
La clave se proporciona en 2 formas: regular y ''noNL''. La versión noNL está incluida en el código anterior, la versión regular es la siguiente:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVGUzbydMZS+fnkGTsUkDKEyFO
GwghR234d5GjPnMIC0RFtXtw2tdcNM8I9Qk+h6fnPHiA7r27iHBfdxTP3oegQJWp
bY2RMwSmOs02eQqpKx4QtIjWqkKk2Gmck5cll9GCoI8AUAA5e0D02T0ZgINDmo5y
GPhGAAmqYrm8YiupwQIDAQAB
-----END PUBLIC KEY-----
First base64 es solo una codificación de algunos datos binarios. Hay más de una forma de codificar, en binario, una clave pública RSA. Sin embargo, si obtuviste esto de OpenSSL es probable que sea una estructura RSAPublicKey
codificada en RSAPublicKey
.
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER } -- e
En general, necesitaría un decodificador ASN.1, Mono.Security.dll proporciona one , pero para una estructura tan simple es posible que desee hacerlo a mano ya que ASN.1 es básicamente una etiqueta , longitud y un valor .
Si su compañero también usa .NET, él / ella puede derivar de makecert https://github.com/mono/mono/blob/bf55818da11240bd108dc51b374fae3d3b5482ce/mcs/tools/security/makecert.cs para generar archivos de certificado y enviar directamente a usted .
En ese caso, puede cargar fácilmente certificados en lugar de bytes sin procesar,
http://www.lextm.com/2012/02/simple-publicprivate-key-signing-sample-code/
Su cadena es la codificación base64 de un SubjectPublicKeyInfo . Puedes usar Bouncycastle.net para decodificarlo así:
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);