Exemple #1
0
        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.");
            }
        }