/// <summary> /// Check an Active Authentication reply from the passport. /// </summary> /// <param name="publicKey">The AA public key read from the passport.</param> /// <param name="message">The original message.</param> /// <param name="signature">The response from the passport</param> /// <returns>True if the signature is correct for this message.</returns> public static bool CheckAA(RsaPublicKeyStructure publicKey, byte[] message, byte[] signature) { SHA1 sha1 = SHA1.Create(); RsaEngine rsa = new RsaEngine(); RsaKeyParameters p = new RsaKeyParameters(false, publicKey.Modulus, publicKey.PublicExponent); rsa.Init(false, p); byte[] digestedMessage = sha1.ComputeHash(message); // should always be 20 bytes byte[] m2 = new byte[8]; Array.Copy(digestedMessage, 0, m2, 0, m2.Length); byte[] plainText = rsa.ProcessBlock(signature, 0, signature.Length); byte[] m1 = recoverMessage(digestedMessage.Length, plainText); Sha1Digest digest = new Sha1Digest(); Iso9796d2Signer signer = new Iso9796d2Signer(rsa, digest); signer.Init(false, p); signer.BlockUpdate(m1, 0, m1.Length); signer.BlockUpdate(m2, 0, m2.Length); return signer.VerifySignature(signature); }
public void DoTest13() { BigInteger modulus = new BigInteger(1, Hex.Decode("CDCBDABBF93BE8E8294E32B055256BBD0397735189BF75816341BB0D488D05D627991221DF7D59835C76A4BB4808ADEEB779E7794504E956ADC2A661B46904CDC71337DD29DDDD454124EF79CFDD7BC2C21952573CEFBA485CC38C6BD2428809B5A31A898A6B5648CAA4ED678D9743B589134B7187478996300EDBA16271A861")); BigInteger pubExp = new BigInteger(1, Hex.Decode("010001")); BigInteger privExp = new BigInteger(1, Hex.Decode("4BA6432AD42C74AA5AFCB6DF60FD57846CBC909489994ABD9C59FE439CC6D23D6DE2F3EA65B8335E796FD7904CA37C248367997257AFBD82B26F1A30525C447A236C65E6ADE43ECAAF7283584B2570FA07B340D9C9380D88EAACFFAEEFE7F472DBC9735C3FF3A3211E8A6BBFD94456B6A33C17A2C4EC18CE6335150548ED126D")); RsaKeyParameters pubParams = new RsaKeyParameters(false, modulus, pubExp); RsaKeyParameters privParams = new RsaKeyParameters(true, modulus, privExp); IAsymmetricBlockCipher rsaEngine = new RsaBlindedEngine(); IDigest digest = new Sha256Digest(); // set challenge to all zero's for verification byte[] challenge = new byte[8]; // DOES NOT USE FINAL BOOLEAN TO INDICATE RECOVERY Iso9796d2Signer signer = new Iso9796d2Signer(rsaEngine, digest, false); // sign signer.Init(true, privParams); signer.BlockUpdate(challenge, 0, challenge.Length); byte[] sig = signer.GenerateSignature(); // verify signer.Init(false, pubParams); signer.BlockUpdate(challenge, 0, challenge.Length); if (!signer.VerifySignature(sig)) { Fail("basic verification failed"); } // === LETS ACTUALLY DO SOME RECOVERY, USING INPUT FROM INTERNAL AUTHENTICATE === signer.Reset(); string args0 = "482E20D1EDDED34359C38F5E7C01203F9D6B2641CDCA5C404D49ADAEDE034C7481D781D043722587761C90468DE69C6585A1E8B9C322F90E1B580EEDAB3F6007D0C366CF92B4DB8B41C8314929DCE2BE889C0129123484D2FD3D12763D2EBFD12AC8E51D7061AFCA1A53DEDEC7B9A617472A78C952CCC72467AE008E5F132994"; digest = new Sha1Digest(); signer = new Iso9796d2Signer(rsaEngine, digest, true); signer.Init(false, pubParams); byte[] signature = Hex.Decode(args0); signer.UpdateWithRecoveredMessage(signature); signer.BlockUpdate(challenge, 0, challenge.Length); if (!signer.VerifySignature(signature)) { Fail("recovered + challenge signature failed"); } // === FINALLY, USING SHA-256 === signer.Reset(); digest = new Sha256Digest(); // NOTE setting implicit to false does not actually do anything for verification !!! signer = new Iso9796d2Signer(rsaEngine, digest, false); signer.Init(true, privParams); // generate NONCE of correct length using some inner knowledge int nonceLength = modulus.BitLength / 8 - 1 - digest.GetDigestSize() - 2; byte[] nonce = new byte[nonceLength]; SecureRandom rnd = new SecureRandom(); rnd.NextBytes(nonce); signer.BlockUpdate(nonce, 0, nonce.Length); signer.BlockUpdate(challenge, 0, challenge.Length); byte[] sig3 = signer.GenerateSignature(); signer.Init(false, pubParams); signer.UpdateWithRecoveredMessage(sig3); signer.BlockUpdate(challenge, 0, challenge.Length); if (signer.VerifySignature(sig3)) { if (signer.HasFullMessage()) { Fail("signer indicates full message"); } byte[] recoverableMessage = signer.GetRecoveredMessage(); // sanity check, normally the nonce is ignored in eMRTD specs (PKI Technical Report) if (!Arrays.AreEqual(nonce, recoverableMessage)) { Fail("Nonce compare with recoverable part of message failed"); } } else { Fail("recoverable + nonce failed."); } }
public virtual void DoTest12() { BigInteger mod = new BigInteger("B3ABE6D91A4020920F8B3847764ECB34C4EB64151A96FDE7B614DC986C810FF2FD73575BDF8532C06004C8B4C8B64F700A50AEC68C0701ED10E8D211A4EA554D", 16); BigInteger pubExp = new BigInteger("65537", 10); BigInteger priExp = new BigInteger("AEE76AE4716F77C5782838F328327012C097BD67E5E892E75C1356E372CCF8EE1AA2D2CBDFB4DA19F703743F7C0BA42B2D69202BA7338C294D1F8B6A5771FF41", 16); RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod, pubExp); RsaKeyParameters privParameters = new RsaKeyParameters(true, mod, priExp); RsaEngine rsa = new RsaEngine(); byte[] data; byte[] m1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; byte[] m2 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; byte[] m3 = { 1, 2, 3, 4, 5, 6, 7, 8 }; // // ISO 9796-2 - Regular Signing // IDigest dig = new Sha1Digest(); Iso9796d2Signer eng = new Iso9796d2Signer(rsa, dig); // // check message bounds // eng.Init(true, privParameters); eng.BlockUpdate(m1, 0, m1.Length); data = eng.GenerateSignature(); eng.Init(false, pubParameters); eng.BlockUpdate(m2, 0, m2.Length); if (eng.VerifySignature(data)) { Fail("failed ISO9796-2 m2 verify Test 12"); } eng.Init(false, pubParameters); eng.BlockUpdate(m3, 0, m3.Length); if (eng.VerifySignature(data)) { Fail("failed ISO9796-2 m3 verify Test 12"); } eng.Init(false, pubParameters); eng.BlockUpdate(m1, 0, m1.Length); if (!eng.VerifySignature(data)) { Fail("failed ISO9796-2 verify Test 12"); } }
public virtual void DoTest5() { RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod3, pub3); RsaKeyParameters privParameters = new RsaKeyParameters(true, mod3, pri3); RsaEngine rsa = new RsaEngine(); byte[] data; // // ISO 9796-2 - Signing // Iso9796d2Signer eng = new Iso9796d2Signer(rsa, new RipeMD160Digest(), true); eng.Init(true, privParameters); eng.Update(msg5[0]); eng.BlockUpdate(msg5, 1, msg5.Length - 1); data = eng.GenerateSignature(); eng.Init(false, pubParameters); if (!IsSameAs(sig5, 0, data)) { Fail("failed ISO9796-2 generation Test 5"); } eng.Update(msg5[0]); eng.BlockUpdate(msg5, 1, msg5.Length - 1); if (!eng.VerifySignature(data)) { Fail("failed ISO9796-2 verify Test 5"); } if (eng.HasFullMessage()) { Fail("fullMessage true - Test 5"); } if (!StartsWith(msg5, eng.GetRecoveredMessage())) { Fail("failed ISO9796-2 partial recovered message Test 5"); } int length = eng.GetRecoveredMessage().Length; if (length >= msg5.Length) { Fail("Test 5 recovered message too long"); } eng = new Iso9796d2Signer(rsa, new RipeMD160Digest(), true); eng.Init(false, pubParameters); eng.UpdateWithRecoveredMessage(sig5); if (!StartsWith(msg5, eng.GetRecoveredMessage())) { Fail("failed ISO9796-2 updateWithRecovered partial recovered message Test 5"); } if (eng.HasFullMessage()) { Fail("fullMessage updateWithRecovered true - Test 5"); } for (int i = length ; i != msg5.Length; i++) { eng.Update(msg5[i]); } if (!eng.VerifySignature(sig5)) { Fail("failed ISO9796-2 verify Test 5"); } if (eng.HasFullMessage()) { Fail("fullMessage updateWithRecovered true - Test 5"); } // should fail eng.UpdateWithRecoveredMessage(sig5); eng.BlockUpdate(msg5, 0, msg5.Length); if (eng.VerifySignature(sig5)) { Fail("failed ISO9796-2 updateWithRecovered verify fail Test 5"); } }
public virtual void DoTest4() { RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod3, pub3); RsaKeyParameters privParameters = new RsaKeyParameters(true, mod3, pri3); RsaEngine rsa = new RsaEngine(); byte[] data; // // ISO 9796-2 - Signing // Iso9796d2Signer eng = new Iso9796d2Signer(rsa, new RipeMD128Digest()); eng.Init(true, privParameters); eng.Update(msg4[0]); eng.BlockUpdate(msg4, 1, msg4.Length - 1); data = eng.GenerateSignature(); eng.Init(false, pubParameters); if (!IsSameAs(sig4, 0, data)) { Fail("failed ISO9796-2 generation Test 4"); } eng.Update(msg4[0]); eng.BlockUpdate(msg4, 1, msg4.Length - 1); if (!eng.VerifySignature(data)) { Fail("failed ISO9796-2 verify Test 4"); } if (eng.HasFullMessage()) { eng = new Iso9796d2Signer(rsa, new RipeMD128Digest()); eng.Init(false, pubParameters); if (!eng.VerifySignature(sig4)) { Fail("failed ISO9796-2 verify and recover Test 4"); } if(!IsSameAs(eng.GetRecoveredMessage(), 0, msg4)) { Fail("failed ISO9796-2 recovered message Test 4"); } // try update with recovered eng.UpdateWithRecoveredMessage(sig4); if(!IsSameAs(eng.GetRecoveredMessage(), 0, msg4)) { Fail("failed ISO9796-2 updateWithRecovered recovered message Test 4"); } if (!eng.VerifySignature(sig4)) { Fail("failed ISO9796-2 updateWithRecovered verify and recover Test 4"); } if(!IsSameAs(eng.GetRecoveredMessage(), 0, msg4)) { Fail("failed ISO9796-2 updateWithRecovered recovered verify message Test 4"); } // should fail eng.UpdateWithRecoveredMessage(sig4); eng.BlockUpdate(msg4, 0, msg4.Length); if (eng.VerifySignature(sig4)) { Fail("failed ISO9796-2 updateWithRecovered verify and recover Test 4"); } } else { Fail("full message flag false - Test 4"); } }