예제 #1
0
        internal static SjclQuad ComputeTag(SjclAes aes, byte[] plaintext, byte[] iv, byte[] adata, int tagLength, int plaintextLengthLength)
        {
            if (tagLength % 2 != 0 || tagLength < 4 || tagLength > 16)
            {
                throw new CryptoException("Tag must be 4, 8, 10, 12, 14 or 16 bytes long");
            }

            // flags + iv + plaintext-length
            var tag   = new SjclQuad(iv, -1);
            var flags = (adata.Length > 0 ? 0x40 : 0) | ((tagLength - 2) << 2) | (plaintextLengthLength - 1);

            tag.SetByte(0, (byte)flags);

            // Append plaintext length
            for (var i = 0; i < plaintextLengthLength; ++i)
            {
                tag.SetByte(15 - i, (byte)(plaintext.Length >> i * 8));
            }

            tag = aes.Encrypt(tag);

            var adataLength = adata.Length;

            if (adataLength > 0)
            {
                var adataWithLength = EncodeAdataLength(adataLength).Concat(adata).ToArray();
                for (var i = 0; i < adataWithLength.Length; i += 16)
                {
                    tag = aes.Encrypt(tag ^ new SjclQuad(adataWithLength, i));
                }
            }

            for (var i = 0; i < plaintext.Length; i += 16)
            {
                tag = aes.Encrypt(tag ^ new SjclQuad(plaintext, i));
            }

            return(tag);
        }
예제 #2
0
        internal static CtrResult ApplyCtr(SjclAes aes, byte[] plaintext, byte[] iv, SjclQuad tag, int tagLength, int plaintextLengthLength)
        {
            // plaintextLength + iv
            var ctr = new SjclQuad(iv, -1);

            ctr.SetByte(0, (byte)(plaintextLengthLength - 1));

            // Encrypt the tag
            var encryptedTag = tag ^ aes.Encrypt(ctr);

            // Encrypt the plaintext
            var ciphertext = new byte[plaintext.Length];

            for (var i = 0; i < plaintext.Length; i += 16)
            {
                ++ctr.D;
                var block = new SjclQuad(plaintext, i) ^ aes.Encrypt(ctr);
                Array.Copy(block.ToBytes(), 0, ciphertext, i, Math.Min(16, plaintext.Length - i));
            }

            return(new CtrResult(ciphertext, encryptedTag));
        }