Exemplo n.º 1
0
        /// <summary>
        /// <para> Based on section B.1.2.2 of the v2.3 GlobalPlatform Card Specification. </para>
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <param name="icv"></param>
        /// <returns></returns>
        public static byte[] Algorithm3(byte[] data, byte[] key, byte[] icv)
        {
            if (data.Length % 8 != 0)
            {
                throw new ArgumentException("Data must be padded to 8-byte blocks.", nameof(data));
            }

            Ensure.HasCount(key, nameof(key), 16);
            Ensure.HasCount(icv, nameof(icv), 8);

            int numBlocks = data.Length / 8;

            byte[] iv;

            if (numBlocks > 1)
            {
                byte[] firstBlocks = data.Take((numBlocks - 1) * 8).ToArray();

                byte[] encFirstBlocks = DES.Encrypt(firstBlocks, key.Take(8).ToArray(), icv, CipherMode.CBC);

                iv = encFirstBlocks.TakeLast(8).ToArray();
            }
            else
            {
                iv = icv;
            }

            byte[] lastBlock    = data.TakeLast(8).ToArray();
            byte[] encLastBlock = TripleDES.Encrypt(lastBlock, key, iv, CipherMode.CBC);
            byte[] mac          = encLastBlock.TakeLast(8).ToArray();

            return(mac);
        }
Exemplo n.º 2
0
        public void PutKey()
        {
            const byte keyVersion    = 0x7F;
            const byte keyIdentifier = 0x01;

            byte[] encryptionkey = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };

            var apdu = PutKeyCommand.Build
                       .WithKeyVersion(keyVersion)
                       .WithKeyIdentifier(keyIdentifier)
                       .UsingEncryptionKey(encryptionkey)
                       .PutFirstKey(KeyTypeCoding.DES, KeyData)
                       .PutSecondKey(KeyTypeCoding.DES, KeyData)
                       .PutThirdKey(KeyTypeCoding.DES, KeyData)
                       .AsApdu();

            apdu.Assert(ApduClass.GlobalPlatform, ApduInstruction.PutKey, keyVersion, keyIdentifier, 0x00);

            apdu.Lc.ShouldAllBeEquivalentTo(1 + 3 * 22);
            apdu.CommandData.First().Should().Be(keyVersion);
            apdu.CommandData.Skip(1).Split(22).ForEach(block =>
            {
                block.First().Should().Be(0x80);
                block.Skip(1).First().Should().Be(0x10);
                block.Skip(2).Take(16).ShouldAllBeEquivalentTo(TripleDES.Encrypt(KeyData, encryptionkey, CipherMode.ECB));
                block.Skip(18).First().Should().Be(0x03);
                block.Skip(19).ShouldAllBeEquivalentTo(KeyCheckValue.Generate(KeyTypeCoding.DES, KeyData));
            });
        }
Exemplo n.º 3
0
        public void TripleDes()
        {
            byte[] plaintext  = { 0x98, 0x26, 0x62, 0x60, 0x55, 0x53, 0x24, 0x4D };
            byte[] key        = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };
            byte[] ciphertext = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 };

            TripleDES.Encrypt(plaintext, key).Should().BeEquivalentTo(ciphertext);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Generates a key check value for the specified key.
        /// <para> Based on section B.6 of the v2.3 GlobalPlatform Card Specification. </para>
        /// </summary>
        /// <param name="keyType"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static byte[] Generate(KeyTypeCoding keyType, byte[] key)
        {
            IEnumerable <byte> data;

            switch (keyType)
            {
            case KeyTypeCoding.DES:
                data = Enumerable.Repeat <byte>(0x00, 8);
                break;

            case KeyTypeCoding.AES:
                data = Enumerable.Repeat <byte>(0x01, 16);
                break;

            default:
                throw new NotSupportedException("Unsupported key type.");
            }

            return(TripleDES.Encrypt(data.ToArray(), key, CipherMode.ECB).Take(3).ToArray());
        }
Exemplo n.º 5
0
        /// <summary>
        /// <para> Based on section B.1.2.1 of the v2.3 GlobalPlatform Card Specification. </para>
        /// </summary>
        /// <param name="data"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static byte[] Algorithm1(byte[] data, byte[] key)
        {
            byte[] ciphertext = TripleDES.Encrypt(data, key);

            return(ciphertext.Skip(ciphertext.Length - 8).Take(8).ToArray());
        }
 private byte[] GenerateSessionKey(SessionKeyType sessionKeyType, byte[] staticKey)
 => TripleDES.Encrypt(this.GenerateDerivationData(sessionKeyType), staticKey);
        public CommandApdu SecureApdu(CommandApdu apdu)
        {
            if (apdu.ExtendedMode)
            {
                throw new InvalidOperationException("Extended commands APDUs are not supported.");
            }

            ApduClass.ByteCoding classByteCoding;

            if (apdu.CLA.IsBitSet(7))
            {
                classByteCoding = ApduClass.ByteCoding.First;
            }
            else if (apdu.CLA.IsBitSet(6))
            {
                classByteCoding = ApduClass.ByteCoding.InterIndustry;
            }
            else
            {
                return(apdu);
            }

            if (this.SecurityLevel.HasFlag(SecurityLevel.CMac) || apdu.INS == ApduInstruction.ExternalAuthenticate)
            {
                switch (classByteCoding)
                {
                case ApduClass.ByteCoding.First:
                    apdu.CLA = apdu.CLA |= 0b00000100;
                    break;

                case ApduClass.ByteCoding.InterIndustry:
                    apdu.CLA = apdu.CLA |= 0b00100000;
                    break;

                default:
                    throw new InvalidOperationException("APDU does not use either First or Interindustry Class Byte coding.");
                }

                var mac = this.GenerateCmac(apdu);

                var data = new List <byte>();
                data.AddRange(apdu.CommandData);
                data.AddRange(mac);

                apdu.CommandData = data.ToArray();
            }

            if (this.SecurityLevel.HasFlag(SecurityLevel.CDecryption) && apdu.INS != ApduInstruction.ExternalAuthenticate)
            {
                var commandData = apdu.CommandData.Take(apdu.CommandData.Count() - 8).ToList();
                var mac         = apdu.CommandData.TakeLast(8);

                byte[] padded = commandData.Pad().ToArray();

                byte[] encrypted = TripleDES.Encrypt(padded, this.EncryptionKey);

                var data = new List <byte>();
                data.AddRange(encrypted);
                data.AddRange(mac);

                apdu.CommandData = data.ToArray();
            }

            return(apdu);
        }