//
// 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);
}