org libreria example digests crypto c# .net cryptography digital-signature bouncycastle

c# - libreria - Verificar la firma de BouncyCastle ECDsa con las bibliotecas.NET ECDsaCng



signature sha256 c# (1)

Un sistema existente generó firmas usando Bouncy Castle (.NET) y necesito verificar estas firmas existentes usando la clase Microsoft ECDsaCng.

Considere el siguiente código que intenta hacer esto:

public static void InterchangeTest() { //AsymmetricCipherKeyPair bKeyPair_0 = Crypto.GenerateEcdsaKey(); String sPassPhrase = "bob is your uncle"; byte[] bPassPhrase = new UTF8Encoding(false).GetBytes(sPassPhrase); int SaltBitSize = 128; int EcdsaBitLength = 521; byte[] bSalt = new byte[SaltBitSize / 8]; new SecureRandom().NextBytes(bSalt); if (EcdsaBitLength != 192 && EcdsaBitLength != 256 && EcdsaBitLength != 521) { throw new ArgumentException("Invalid EcdsaBitLength length () " + EcdsaBitLength + " ECDSA supports 192, 256, and 521 bit lengths."); } string curveName = "P-" + EcdsaBitLength.ToString(); X9ECParameters ecP = NistNamedCurves.GetByName(curveName); ECDomainParameters ecSpec = new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed()); IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDH"); g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom())); AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair(); ECPrivateKeyParameters mPrivateKey = (ECPrivateKeyParameters)aKeyPair.Private; ECPublicKeyParameters mPublicKey = (ECPublicKeyParameters)aKeyPair.Public; byte[] bPrivateKey = ((ECPrivateKeyParameters)aKeyPair.Private).D.ToByteArray(); String SignerName = "SHA-256withECDSA"; ISigner bSigner = SignerUtilities.GetSigner(SignerName); bSigner.Init(true, aKeyPair.Private); bSigner.BlockUpdate(bPassPhrase, 0, bPassPhrase.Length); byte[] bouncySignature = bSigner.GenerateSignature(); ISigner bVerifier = SignerUtilities.GetSigner(SignerName); bVerifier.Init(false, aKeyPair.Public); bVerifier.BlockUpdate(bPassPhrase, 0, bPassPhrase.Length); bool passed = bVerifier.VerifySignature(bouncySignature); Console.WriteLine("Verified with Bouncy: " + passed); var xmlImport = "<ECDSAKeyValue xmlns=''http://www.w3.org/2001/04/xmldsig-more#''>/n" + " <DomainParameters>/n" + " <NamedCurve URN=''urn:oid:1.3.132.0.35'' />/n" + " </DomainParameters >/n" + " <PublicKey >/n" + " <X Value=''" + ((ECPublicKeyParameters)aKeyPair.Public).Q.X.ToBigInteger().ToString() + "'' xsi:type=''PrimeFieldElemType'' xmlns:xsi=''http://www.w3.org/2001/XMLSchema-instance'' />/n" + " <Y Value=''" + ((ECPublicKeyParameters)aKeyPair.Public).Q.Y.ToBigInteger().ToString() + "'' xsi:type=''PrimeFieldElemType'' xmlns:xsi=''http://www.w3.org/2001/XMLSchema-instance'' />/n" + " </PublicKey >/n" + " </ECDSAKeyValue>"; //using (StreamWriter outputFile = new StreamWriter(@"C:/Dev/x2.txt")) //{ // outputFile.WriteLine(xmlImport); //} ECDsaCng eccImporter = new ECDsaCng(); eccImporter.FromXmlString(xmlImport, ECKeyXmlFormat.Rfc4050); Console.WriteLine("hash algorithm = " + eccImporter.HashAlgorithm + " Probably " + CngAlgorithm.Sha256); Console.WriteLine("Signature algorithm = " + eccImporter.SignatureAlgorithm + " Probably ECDsa"); Console.WriteLine("After import, key size = " + eccImporter.KeySize + " probably 521"); try { if (eccImporter.VerifyData(bPassPhrase, bouncySignature)) { Console.WriteLine("Verified the signature from bouncy castle using .NET"); } } catch (CryptographicException e) { // "The parameter is incorrect" Console.WriteLine("Did not verify bouncy signature with .NET because: " + e.Message); } CngKey msKey = CngKey.Create(CngAlgorithm.ECDsaP521, null, new CngKeyCreationParameters { ExportPolicy = CngExportPolicies.AllowPlaintextArchiving }); ECDsaCng ms_ecdsaCNG = new ECDsaCng(msKey); String xmlExport = ms_ecdsaCNG.ToXmlString(ECKeyXmlFormat.Rfc4050); eccImporter = new ECDsaCng(); eccImporter.FromXmlString(xmlExport, ECKeyXmlFormat.Rfc4050); byte[] ms_SignedData = ms_ecdsaCNG.SignData(bPassPhrase); Console.WriteLine("Verify .NET signature with .NET: " + ms_ecdsaCNG.VerifyData(bPassPhrase, ms_SignedData)); Console.WriteLine("Verify .NET signature with imported .NET: " + eccImporter.VerifyData(bPassPhrase, ms_SignedData)); //Console.WriteLine(); //Console.WriteLine(xmlExport); //Console.WriteLine(); }

Todo funciona bien hasta que intento verificar la firma con las clases de Microsoft, en cuyo punto genera una excepción que indica que el parámetro es incorrecto.

¿Alguna idea?


Maarten Bodewes tiene razón. Mi problema es que la firma está codificada usando BouncyCastly usando el formato ASN.1 / DER. MS usa un formato más pequeño (creo que es IEEE P-1393). Entonces, escribí esta pequeña rutina en C # para transformar las firmas.

public static byte[] ConvertDerToP1393(byte[] data) { byte[] b = new byte[132]; int totalLength = data[1]; int n = 0; int offset = 4; int thisLength = data[offset++]; if (data[offset] == 0) { // Negative number! ++offset; --thisLength; } for (int i= thisLength; i < 66; ++i) { b[n++] = 0; } if (thisLength > 66) { System.Console.WriteLine("BAD, first number is too big! " + thisLength); } else { for (int i = 0; i < thisLength; ++i) { b[n++] = data[offset++]; } } ++offset; thisLength = data[offset++]; for (int i = thisLength; i < 66; ++i){ b[n++] = 0; } if (thisLength > 66) { System.Console.WriteLine("BAD, second number is too big! " + thisLength); } else { for (int i = 0; i < thisLength; ++i) { b[n++] = data[offset++]; } } return b; }

Aunque solo he realizado pruebas limitadas, el código ha funcionado con mis pruebas.