SymmetricKeyWrap.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / clr / src / ManagedLibraries / Security / System / Security / Cryptography / Xml / SymmetricKeyWrap.cs / 1 / SymmetricKeyWrap.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
//----------------------------------------------------------------------------
 
// 
// SymmetricKeyWrap.cs
// 
// 04/01/2002
//
//---------------------------------------------------------------------------
 
namespace System.Security.Cryptography.Xml
{ 
    using System; 
    using System.Security.Cryptography;
 
    // abstract class providing symmetric key wrap implementation
    internal static class SymmetricKeyWrap {
        private readonly static byte[] s_rgbTripleDES_KW_IV = {0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05};
        private readonly static byte[] s_rgbAES_KW_IV = {0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6}; 

        // 
        // internal static methods 
        //
 
        // CMS TripleDES KeyWrap as described in "http://www.w3.org/2001/04/xmlenc#kw-tripledes"
        internal static byte[] TripleDESKeyWrapEncrypt (byte[] rgbKey, byte[] rgbWrappedKeyData) {
            // checksum the key
            SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider(); 
            byte[] rgbCKS = sha.ComputeHash(rgbWrappedKeyData);
 
            // generate a random IV 
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            byte[] rgbIV = new byte[8]; 
            rng.GetBytes(rgbIV);

            // rgbWKCS = rgbWrappedKeyData | (first 8 bytes of the hash)
            byte[] rgbWKCKS = new byte[rgbWrappedKeyData.Length + 8]; 
            TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
            // Don't add padding, use CBC mode: for example, a 192 bits key will yield 40 bytes of encrypted data 
            tripleDES.Padding = PaddingMode.None; 
            ICryptoTransform enc1 = tripleDES.CreateEncryptor(rgbKey, rgbIV);
            Buffer.BlockCopy(rgbWrappedKeyData, 0, rgbWKCKS, 0, rgbWrappedKeyData.Length); 
            Buffer.BlockCopy(rgbCKS, 0, rgbWKCKS, rgbWrappedKeyData.Length, 8);
            byte[] temp1 = enc1.TransformFinalBlock(rgbWKCKS, 0, rgbWKCKS.Length);
            byte[] temp2 = new byte[rgbIV.Length + temp1.Length];
            Buffer.BlockCopy(rgbIV, 0, temp2, 0, rgbIV.Length); 
            Buffer.BlockCopy(temp1, 0, temp2, rgbIV.Length, temp1.Length);
            // temp2 = REV (rgbIV | E_k(rgbWrappedKeyData | rgbCKS)) 
            Array.Reverse(temp2); 

            ICryptoTransform enc2 = tripleDES.CreateEncryptor(rgbKey, s_rgbTripleDES_KW_IV); 
            return enc2.TransformFinalBlock(temp2, 0, temp2.Length);
        }

        internal static byte[] TripleDESKeyWrapDecrypt (byte[] rgbKey, byte[] rgbEncryptedWrappedKeyData) { 
            // Check to see whether the length of the encrypted key is reasonable
            if (rgbEncryptedWrappedKeyData.Length != 32 && rgbEncryptedWrappedKeyData.Length != 40 
                && rgbEncryptedWrappedKeyData.Length != 48) 
                throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_KW_BadKeySize"));
 
            TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
            // Assume no padding, use CBC mode
            tripleDES.Padding = PaddingMode.None;
            ICryptoTransform dec1 = tripleDES.CreateDecryptor(rgbKey, s_rgbTripleDES_KW_IV); 
            byte[] temp2 = dec1.TransformFinalBlock(rgbEncryptedWrappedKeyData, 0, rgbEncryptedWrappedKeyData.Length);
            Array.Reverse(temp2); 
            // Get the IV and temp1 
            byte[] rgbIV = new byte[8];
            Buffer.BlockCopy(temp2, 0, rgbIV, 0, 8); 
            byte[] temp1 = new byte[temp2.Length - rgbIV.Length];
            Buffer.BlockCopy(temp2, 8, temp1, 0, temp1.Length);

            ICryptoTransform dec2 = tripleDES.CreateDecryptor(rgbKey, rgbIV); 
            byte[] rgbWKCKS = dec2.TransformFinalBlock(temp1, 0, temp1.Length);
 
            // checksum the key 
            byte[] rgbWrappedKeyData = new byte[rgbWKCKS.Length - 8];
            Buffer.BlockCopy(rgbWKCKS, 0, rgbWrappedKeyData, 0, rgbWrappedKeyData.Length); 
            SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
            byte[] rgbCKS = sha.ComputeHash(rgbWrappedKeyData);
            for (int index = rgbWrappedKeyData.Length, index1 = 0; index < rgbWKCKS.Length; index++, index1++)
                if (rgbWKCKS[index] != rgbCKS[index1]) 
                    throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_BadWrappedKeySize"));
            return rgbWrappedKeyData; 
        } 

        // AES KeyWrap described in "http://www.w3.org/2001/04/xmlenc#kw-aes***", as suggested by NIST 
        internal static byte[] AESKeyWrapEncrypt (byte[] rgbKey, byte[] rgbWrappedKeyData) {
            int N = rgbWrappedKeyData.Length >> 3;
            // The information wrapped need not actually be a key, but it needs to be a multiple of 64 bits
            if ((rgbWrappedKeyData.Length % 8 != 0) || N <= 0) 
                throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_KW_BadKeySize"));
 
            RijndaelManaged rijn = new RijndaelManaged(); 
            rijn.Key = rgbKey;
            // Use ECB mode, no padding 
            rijn.Mode = CipherMode.ECB;
            rijn.Padding = PaddingMode.None;
            ICryptoTransform enc = rijn.CreateEncryptor();
            // special case: only 1 block -- 8 bytes 
            if (N == 1) {
                // temp = 0xa6a6a6a6a6a6a6a6 | P(1) 
                byte[] temp = new byte[s_rgbAES_KW_IV.Length + rgbWrappedKeyData.Length]; 
                Buffer.BlockCopy(s_rgbAES_KW_IV, 0, temp, 0, s_rgbAES_KW_IV.Length);
                Buffer.BlockCopy(rgbWrappedKeyData, 0, temp, s_rgbAES_KW_IV.Length, rgbWrappedKeyData.Length); 
                return enc.TransformFinalBlock(temp, 0, temp.Length);
            }
            // second case: more than 1 block
            Int64 t = 0; 
            byte[] rgbOutput = new byte[(N+1) << 3];
            // initialize the R_i's 
            Buffer.BlockCopy(rgbWrappedKeyData, 0, rgbOutput, 8, rgbWrappedKeyData.Length); 
            byte[] rgbA = new byte[8];
            byte[] rgbBlock = new byte[16]; 
            Buffer.BlockCopy(s_rgbAES_KW_IV, 0, rgbA, 0, 8);
            for (int j=0; j<=5; j++) {
                for (int i=1; i<=N; i++) {
                    t = i + j*N; 
                    Buffer.BlockCopy(rgbA, 0, rgbBlock, 0, 8);
                    Buffer.BlockCopy(rgbOutput, 8*i, rgbBlock, 8, 8); 
                    byte[] rgbB = enc.TransformFinalBlock(rgbBlock, 0, 16); 
                    for (int k=0; k<8; k++) {
                        byte tmp = (byte) ((t >> (8*(7-k))) & 0xFF); 
                        rgbA[k] = (byte) (tmp ^ rgbB[k]);
                    }
                    Buffer.BlockCopy(rgbB, 8, rgbOutput, 8*i, 8);
                } 
            }
            // Set the first block of rgbOutput to rgbA 
            Buffer.BlockCopy(rgbA, 0, rgbOutput, 0, 8); 
            return rgbOutput;
        } 

        internal static byte[] AESKeyWrapDecrypt (byte[] rgbKey, byte[] rgbEncryptedWrappedKeyData) {
            int N = (rgbEncryptedWrappedKeyData.Length >> 3) - 1;
            // The information wrapped need not actually be a key, but it needs to be a multiple of 64 bits 
            if ((rgbEncryptedWrappedKeyData.Length % 8 != 0) || N <= 0)
                throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_KW_BadKeySize")); 
 
            byte[] rgbOutput = new byte[N << 3];
            RijndaelManaged rijn = new RijndaelManaged(); 
            rijn.Key = rgbKey;
            // Use ECB mode, no padding
            rijn.Mode = CipherMode.ECB;
            rijn.Padding = PaddingMode.None; 
            ICryptoTransform dec = rijn.CreateDecryptor();
            // special case: only 1 block -- 8 bytes 
            if (N == 1) { 
                byte[] temp = dec.TransformFinalBlock(rgbEncryptedWrappedKeyData, 0, rgbEncryptedWrappedKeyData.Length);
                // checksum the key 
                for (int index = 0; index < 8; index++)
                    if (temp[index] != s_rgbAES_KW_IV[index])
                        throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_BadWrappedKeySize"));
                // rgbOutput is LSB(temp) 
                Buffer.BlockCopy(temp, 8, rgbOutput, 0, 8);
                return rgbOutput; 
            } 
            // second case: more than 1 block
            Int64 t = 0; 
            // initialize the C_i's
            Buffer.BlockCopy(rgbEncryptedWrappedKeyData, 8, rgbOutput, 0, rgbOutput.Length);
            byte[] rgbA = new byte[8];
            byte[] rgbBlock = new byte[16]; 
            Buffer.BlockCopy(rgbEncryptedWrappedKeyData, 0, rgbA, 0, 8);
            for (int j=5; j>=0; j--) { 
                for (int i=N; i>=1; i--) { 
                    t = i + j*N;
                    for (int k=0; k<8; k++) { 
                        byte tmp = (byte) ((t >> (8*(7-k))) & 0xFF);
                        rgbA[k] ^= tmp;
                    }
                    Buffer.BlockCopy(rgbA, 0, rgbBlock, 0, 8); 
                    Buffer.BlockCopy(rgbOutput, 8*(i-1), rgbBlock, 8, 8);
                    byte[] rgbB = dec.TransformFinalBlock(rgbBlock, 0, 16); 
                    Buffer.BlockCopy(rgbB, 8, rgbOutput, 8*(i-1), 8); 
                    Buffer.BlockCopy(rgbB, 0, rgbA, 0, 8);
                } 
            }
            // checksum the key
            for (int index = 0; index < 8; index++)
                if (rgbA[index] != s_rgbAES_KW_IV[index]) 
                    throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_BadWrappedKeySize"));
            return rgbOutput; 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
//----------------------------------------------------------------------------
 
// 
// SymmetricKeyWrap.cs
// 
// 04/01/2002
//
//---------------------------------------------------------------------------
 
namespace System.Security.Cryptography.Xml
{ 
    using System; 
    using System.Security.Cryptography;
 
    // abstract class providing symmetric key wrap implementation
    internal static class SymmetricKeyWrap {
        private readonly static byte[] s_rgbTripleDES_KW_IV = {0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05};
        private readonly static byte[] s_rgbAES_KW_IV = {0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6}; 

        // 
        // internal static methods 
        //
 
        // CMS TripleDES KeyWrap as described in "http://www.w3.org/2001/04/xmlenc#kw-tripledes"
        internal static byte[] TripleDESKeyWrapEncrypt (byte[] rgbKey, byte[] rgbWrappedKeyData) {
            // checksum the key
            SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider(); 
            byte[] rgbCKS = sha.ComputeHash(rgbWrappedKeyData);
 
            // generate a random IV 
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            byte[] rgbIV = new byte[8]; 
            rng.GetBytes(rgbIV);

            // rgbWKCS = rgbWrappedKeyData | (first 8 bytes of the hash)
            byte[] rgbWKCKS = new byte[rgbWrappedKeyData.Length + 8]; 
            TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
            // Don't add padding, use CBC mode: for example, a 192 bits key will yield 40 bytes of encrypted data 
            tripleDES.Padding = PaddingMode.None; 
            ICryptoTransform enc1 = tripleDES.CreateEncryptor(rgbKey, rgbIV);
            Buffer.BlockCopy(rgbWrappedKeyData, 0, rgbWKCKS, 0, rgbWrappedKeyData.Length); 
            Buffer.BlockCopy(rgbCKS, 0, rgbWKCKS, rgbWrappedKeyData.Length, 8);
            byte[] temp1 = enc1.TransformFinalBlock(rgbWKCKS, 0, rgbWKCKS.Length);
            byte[] temp2 = new byte[rgbIV.Length + temp1.Length];
            Buffer.BlockCopy(rgbIV, 0, temp2, 0, rgbIV.Length); 
            Buffer.BlockCopy(temp1, 0, temp2, rgbIV.Length, temp1.Length);
            // temp2 = REV (rgbIV | E_k(rgbWrappedKeyData | rgbCKS)) 
            Array.Reverse(temp2); 

            ICryptoTransform enc2 = tripleDES.CreateEncryptor(rgbKey, s_rgbTripleDES_KW_IV); 
            return enc2.TransformFinalBlock(temp2, 0, temp2.Length);
        }

        internal static byte[] TripleDESKeyWrapDecrypt (byte[] rgbKey, byte[] rgbEncryptedWrappedKeyData) { 
            // Check to see whether the length of the encrypted key is reasonable
            if (rgbEncryptedWrappedKeyData.Length != 32 && rgbEncryptedWrappedKeyData.Length != 40 
                && rgbEncryptedWrappedKeyData.Length != 48) 
                throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_KW_BadKeySize"));
 
            TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
            // Assume no padding, use CBC mode
            tripleDES.Padding = PaddingMode.None;
            ICryptoTransform dec1 = tripleDES.CreateDecryptor(rgbKey, s_rgbTripleDES_KW_IV); 
            byte[] temp2 = dec1.TransformFinalBlock(rgbEncryptedWrappedKeyData, 0, rgbEncryptedWrappedKeyData.Length);
            Array.Reverse(temp2); 
            // Get the IV and temp1 
            byte[] rgbIV = new byte[8];
            Buffer.BlockCopy(temp2, 0, rgbIV, 0, 8); 
            byte[] temp1 = new byte[temp2.Length - rgbIV.Length];
            Buffer.BlockCopy(temp2, 8, temp1, 0, temp1.Length);

            ICryptoTransform dec2 = tripleDES.CreateDecryptor(rgbKey, rgbIV); 
            byte[] rgbWKCKS = dec2.TransformFinalBlock(temp1, 0, temp1.Length);
 
            // checksum the key 
            byte[] rgbWrappedKeyData = new byte[rgbWKCKS.Length - 8];
            Buffer.BlockCopy(rgbWKCKS, 0, rgbWrappedKeyData, 0, rgbWrappedKeyData.Length); 
            SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider();
            byte[] rgbCKS = sha.ComputeHash(rgbWrappedKeyData);
            for (int index = rgbWrappedKeyData.Length, index1 = 0; index < rgbWKCKS.Length; index++, index1++)
                if (rgbWKCKS[index] != rgbCKS[index1]) 
                    throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_BadWrappedKeySize"));
            return rgbWrappedKeyData; 
        } 

        // AES KeyWrap described in "http://www.w3.org/2001/04/xmlenc#kw-aes***", as suggested by NIST 
        internal static byte[] AESKeyWrapEncrypt (byte[] rgbKey, byte[] rgbWrappedKeyData) {
            int N = rgbWrappedKeyData.Length >> 3;
            // The information wrapped need not actually be a key, but it needs to be a multiple of 64 bits
            if ((rgbWrappedKeyData.Length % 8 != 0) || N <= 0) 
                throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_KW_BadKeySize"));
 
            RijndaelManaged rijn = new RijndaelManaged(); 
            rijn.Key = rgbKey;
            // Use ECB mode, no padding 
            rijn.Mode = CipherMode.ECB;
            rijn.Padding = PaddingMode.None;
            ICryptoTransform enc = rijn.CreateEncryptor();
            // special case: only 1 block -- 8 bytes 
            if (N == 1) {
                // temp = 0xa6a6a6a6a6a6a6a6 | P(1) 
                byte[] temp = new byte[s_rgbAES_KW_IV.Length + rgbWrappedKeyData.Length]; 
                Buffer.BlockCopy(s_rgbAES_KW_IV, 0, temp, 0, s_rgbAES_KW_IV.Length);
                Buffer.BlockCopy(rgbWrappedKeyData, 0, temp, s_rgbAES_KW_IV.Length, rgbWrappedKeyData.Length); 
                return enc.TransformFinalBlock(temp, 0, temp.Length);
            }
            // second case: more than 1 block
            Int64 t = 0; 
            byte[] rgbOutput = new byte[(N+1) << 3];
            // initialize the R_i's 
            Buffer.BlockCopy(rgbWrappedKeyData, 0, rgbOutput, 8, rgbWrappedKeyData.Length); 
            byte[] rgbA = new byte[8];
            byte[] rgbBlock = new byte[16]; 
            Buffer.BlockCopy(s_rgbAES_KW_IV, 0, rgbA, 0, 8);
            for (int j=0; j<=5; j++) {
                for (int i=1; i<=N; i++) {
                    t = i + j*N; 
                    Buffer.BlockCopy(rgbA, 0, rgbBlock, 0, 8);
                    Buffer.BlockCopy(rgbOutput, 8*i, rgbBlock, 8, 8); 
                    byte[] rgbB = enc.TransformFinalBlock(rgbBlock, 0, 16); 
                    for (int k=0; k<8; k++) {
                        byte tmp = (byte) ((t >> (8*(7-k))) & 0xFF); 
                        rgbA[k] = (byte) (tmp ^ rgbB[k]);
                    }
                    Buffer.BlockCopy(rgbB, 8, rgbOutput, 8*i, 8);
                } 
            }
            // Set the first block of rgbOutput to rgbA 
            Buffer.BlockCopy(rgbA, 0, rgbOutput, 0, 8); 
            return rgbOutput;
        } 

        internal static byte[] AESKeyWrapDecrypt (byte[] rgbKey, byte[] rgbEncryptedWrappedKeyData) {
            int N = (rgbEncryptedWrappedKeyData.Length >> 3) - 1;
            // The information wrapped need not actually be a key, but it needs to be a multiple of 64 bits 
            if ((rgbEncryptedWrappedKeyData.Length % 8 != 0) || N <= 0)
                throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_KW_BadKeySize")); 
 
            byte[] rgbOutput = new byte[N << 3];
            RijndaelManaged rijn = new RijndaelManaged(); 
            rijn.Key = rgbKey;
            // Use ECB mode, no padding
            rijn.Mode = CipherMode.ECB;
            rijn.Padding = PaddingMode.None; 
            ICryptoTransform dec = rijn.CreateDecryptor();
            // special case: only 1 block -- 8 bytes 
            if (N == 1) { 
                byte[] temp = dec.TransformFinalBlock(rgbEncryptedWrappedKeyData, 0, rgbEncryptedWrappedKeyData.Length);
                // checksum the key 
                for (int index = 0; index < 8; index++)
                    if (temp[index] != s_rgbAES_KW_IV[index])
                        throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_BadWrappedKeySize"));
                // rgbOutput is LSB(temp) 
                Buffer.BlockCopy(temp, 8, rgbOutput, 0, 8);
                return rgbOutput; 
            } 
            // second case: more than 1 block
            Int64 t = 0; 
            // initialize the C_i's
            Buffer.BlockCopy(rgbEncryptedWrappedKeyData, 8, rgbOutput, 0, rgbOutput.Length);
            byte[] rgbA = new byte[8];
            byte[] rgbBlock = new byte[16]; 
            Buffer.BlockCopy(rgbEncryptedWrappedKeyData, 0, rgbA, 0, 8);
            for (int j=5; j>=0; j--) { 
                for (int i=N; i>=1; i--) { 
                    t = i + j*N;
                    for (int k=0; k<8; k++) { 
                        byte tmp = (byte) ((t >> (8*(7-k))) & 0xFF);
                        rgbA[k] ^= tmp;
                    }
                    Buffer.BlockCopy(rgbA, 0, rgbBlock, 0, 8); 
                    Buffer.BlockCopy(rgbOutput, 8*(i-1), rgbBlock, 8, 8);
                    byte[] rgbB = dec.TransformFinalBlock(rgbBlock, 0, 16); 
                    Buffer.BlockCopy(rgbB, 8, rgbOutput, 8*(i-1), 8); 
                    Buffer.BlockCopy(rgbB, 0, rgbA, 0, 8);
                } 
            }
            // checksum the key
            for (int index = 0; index < 8; index++)
                if (rgbA[index] != s_rgbAES_KW_IV[index]) 
                    throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_BadWrappedKeySize"));
            return rgbOutput; 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK