示例#1
0
        private static byte[] CalculateMac(byte[] key, byte[] nonce, byte[] data, byte[] associatedData, int signatureLength)
        {
            byte[] messageToAuthenticate = BuildB0Block(nonce, true, signatureLength, data.Length);
            if (associatedData.Length > 0)
            {
                if (associatedData.Length >= 65280)
                {
                    throw new NotSupportedException("Associated data length of 65280 or more is not supported");
                }

                byte[] associatedDataLength = BigEndianConverter.GetBytes((ushort)associatedData.Length);
                messageToAuthenticate = ByteUtils.Concatenate(messageToAuthenticate, associatedDataLength);
                messageToAuthenticate = ByteUtils.Concatenate(messageToAuthenticate, associatedData);
                int associatedDataPaddingLength = (16 - (messageToAuthenticate.Length % 16)) % 16;
                messageToAuthenticate = ByteUtils.Concatenate(messageToAuthenticate, new byte[associatedDataPaddingLength]);
            }

            messageToAuthenticate = ByteUtils.Concatenate(messageToAuthenticate, data);

            int dataPaddingLength = (16 - (messageToAuthenticate.Length % 16)) % 16;

            messageToAuthenticate = ByteUtils.Concatenate(messageToAuthenticate, new byte[dataPaddingLength]);

            byte[] encrypted = AesEncrypt(key, new byte[16], messageToAuthenticate, CipherMode.CBC);

            return(ByteReader.ReadBytes(encrypted, messageToAuthenticate.Length - 16, signatureLength));
        }
示例#2
0
        public static byte[] CalculateAesCmac(byte[] key, byte[] data)
        {
            // SubKey generation
            // step 1, AES-128 with key K is applied to an all-zero input block.
            byte[] L = AESEncrypt(key, new byte[16], new byte[16]);

            // step 2, K1 is derived through the following operation:
            byte[] FirstSubkey = Rol(L); //If the most significant bit of L is equal to 0, K1 is the left-shift of L by 1 bit.
            if ((L[0] & 0x80) == 0x80)
            {
                FirstSubkey[15] ^= 0x87; // Otherwise, K1 is the exclusive-OR of const_Rb and the left-shift of L by 1 bit.
            }
            // step 3, K2 is derived through the following operation:
            byte[] SecondSubkey = Rol(FirstSubkey); // If the most significant bit of K1 is equal to 0, K2 is the left-shift of K1 by 1 bit.
            if ((FirstSubkey[0] & 0x80) == 0x80)
            {
                SecondSubkey[15] ^= 0x87; // Otherwise, K2 is the exclusive-OR of const_Rb and the left-shift of K1 by 1 bit.
            }
            // MAC computing
            if (((data.Length != 0) && (data.Length % 16 == 0)) == true)
            {
                // If the size of the input message block is equal to a positive multiple of the block size (namely, 128 bits),
                // the last block shall be exclusive-OR'ed with K1 before processing
                for (int j = 0; j < FirstSubkey.Length; j++)
                {
                    data[data.Length - 16 + j] ^= FirstSubkey[j];
                }
            }
            else
            {
                // Otherwise, the last block shall be padded with 10^i
                byte[] padding = new byte[16 - data.Length % 16];
                padding[0] = 0x80;

                data = ByteUtils.Concatenate(data, padding);

                // and exclusive-OR'ed with K2
                for (int j = 0; j < SecondSubkey.Length; j++)
                {
                    data[data.Length - 16 + j] ^= SecondSubkey[j];
                }
            }

            // The result of the previous process will be the input of the last encryption.
            byte[] encResult = AESEncrypt(key, new byte[16], data);

            byte[] HashValue = new byte[16];
            Array.Copy(encResult, encResult.Length - HashValue.Length, HashValue, 0, HashValue.Length);

            return(HashValue);
        }