/// <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); }
public void Des() { byte[] plaintext = { 0x67, 0x5a, 0x69, 0x67, 0x5e, 0x5a, 0x6b, 0x5a }; byte[] key = { 0x5b, 0x5a, 0x57, 0x67, 0x6a, 0x56, 0x67, 0x6e }; byte[] ciphertext = { 0x97, 0x4a, 0xff, 0xbf, 0x86, 0x02, 0x2d, 0x1f }; DES.Encrypt(plaintext, key).Should().BeEquivalentTo(ciphertext); }
private byte[] GenerateCmac(CommandApdu apdu) { byte[] icv = this.CMac.All(x => x == 0x00) ? this.CMac : DES.Encrypt(this.CMac, this.CMacKey.Take(8).ToArray()); var data = GetDataForCmac(apdu); byte[] mac = MAC.Algorithm3(data, this.CMacKey, icv); return(this.CMac = mac); }