private static bool _VerifyStandardEncryptionKey( HashAlgorithm hAlg, _EncryptionInfo ei, byte[] hFinalPrev) { var pos = ei.verifierOffset; var evi = new byte[16]; var evh = new byte[32]; System.Array.Copy(ei.bytes, pos + 20, evi, 0, evi.Length); System.Array.Copy(ei.bytes, pos + 40, evh, 0, evh.Length); var dvi = new byte[evi.Length]; var dvh = new byte[evh.Length]; var cAlg = _CreateCipherAlgorithmForKey(ei); cAlg.Key = _MakeEncryptionKey(hAlg, ei, hFinalPrev, _ToBytes(0)); using (var dec = cAlg.CreateDecryptor()) { dec.TransformBlock(evi, 0, dvi.Length, dvi, 0); dec.TransformBlock(evh, 0, dvh.Length, dvh, 0); } cAlg.Clear(); var hv = hAlg.ComputeHash(dvi); for (var n = 0; n < hv.Length; ++n) { if (hv[n] != dvh[n]) { return(false); } } return(true); }
private static byte[] _MakeDataEncryptionKey( HashAlgorithm hAlg, _EncryptionInfo ei, byte[] hFinalPrev) { byte[] bk; if (ei.isStandardEncryption) { bk = _ToBytes(0); return(_MakeStandardEncryptionKey(hAlg, ei, hFinalPrev, bk)); } bk = new byte[] { 0x14, 0x6E, 0x0B, 0xE7, 0xAB, 0xAC, 0xD0, 0xD6 }; var ek = _MakeEncryptionKey(hAlg, ei, hFinalPrev, bk); var node = ei.encryptedKeyNode; var ekv = System.Convert.FromBase64String( node.GetAttribute("encryptedKeyValue") ); var cAlg = _CreateCipherAlgorithmForKey(ei); cAlg.Key = ek; cAlg.IV = _MakeIv(node); var dkv = new byte[ekv.Length]; using (var dec = cAlg.CreateDecryptor()) { dec.TransformBlock(ekv, 0, dkv.Length, dkv, 0); } cAlg.Clear(); return(dkv); }
private static string _VerifyEncryptionInfo(_EncryptionInfo ei) { if (ei.isExtensibleEncryption) { return("Extensible encryption is not supported."); } if (!ei.isStandardEncryption && !ei.isAgileEncryption) { return("Unknown encryption version."); } if (ei.isStandardEncryption) { var cAlgId = _ToU32(ei.bytes, 20); var hAlgId = _ToU32(ei.bytes, 24); if (cAlgId != 0x660E && cAlgId != 0x660F && cAlgId != 0x6610) { return(string.Format( "'{0:X8}' is invalid 'AlgID' value.", cAlgId )); } if (hAlgId != 0x8004) { return(string.Format( "'{0:X8}' is invalid 'AlgIDHash' value.", hAlgId )); } return(null); } XmlElement node = null; string algName = null; System.Func <string> algNameError = () => { return(string.Format( "<{0}/> '{1}' is not supported.", node.Name, algName )); }; node = ei.encryptedKeyNode; algName = node.GetAttribute("hashAlgorithm"); if (!_hashAlgorithmCreators.ContainsKey(algName)) { return(algNameError()); } algName = node.GetAttribute("cipherAlgorithm"); if (!_cipherAlgorithmCreators.ContainsKey(algName)) { return(algNameError()); } node = ei.keyDataNode; algName = node.GetAttribute("hashAlgorithm"); if (!_hashAlgorithmCreators.ContainsKey(algName)) { return(algNameError()); } algName = node.GetAttribute("cipherAlgorithm"); if (!_cipherAlgorithmCreators.ContainsKey(algName)) { return(algNameError()); } return(null); }
private static IEnumerable <int> _DecryptPackage( _EncryptionInfo ei, byte[] encryptionKey, byte[] encryptedPackage, byte[] output, int startSegment, int segmentCount = -1) { const int SegSz = 4096; var src = encryptedPackage; var dst = output; var cAlg = _CreateCipherAlgorithmForData(ei); cAlg.Key = encryptionKey; var end = segmentCount * SegSz; if (end < 0 || end > dst.Length) { end = dst.Length; } var seg = startSegment; for (var n = seg * SegSz; n < end; n += SegSz, ++seg) { if (ei.isAgileEncryption) { cAlg.IV = _MakeIv(ei.keyDataNode, _ToBytes((uint)seg)); } var count = (SegSz < end - n) ? SegSz : (end - n); var dec = cAlg.CreateDecryptor(); dec.TransformBlock(src, 8 + n, count, dst, n); dec.Dispose(); yield return(count); } cAlg.Clear(); }
SymmetricAlgorithm _CreateCipherAlgorithmForKey(_EncryptionInfo ei) { if (ei.isStandardEncryption) { return(_CreateCipherAlgorithmForData(ei)); } return(_CreateCipherAlgorithm(ei.encryptedKeyNode)); }
private static bool _VerifyEncryptionKey( HashAlgorithm hAlg, _EncryptionInfo ei, byte[] key) { if (ei.isAgileEncryption) { return(_VerifyAgileEncryptionKey(hAlg, ei, key)); } return(_VerifyStandardEncryptionKey(hAlg, ei, key)); }
private static byte[] _MakeEncryptionKey( HashAlgorithm hAlg, _EncryptionInfo ei, byte[] hFinalPrev, byte[] blockKey) { if (ei.isAgileEncryption) { return(_MakeAgileEncryptionKey(hAlg, ei, hFinalPrev, blockKey)); } return(_MakeStandardEncryptionKey(hAlg, ei, hFinalPrev, blockKey)); }
HashAlgorithm _CreateHashAlgorithmForData(_EncryptionInfo ei) { if (ei.isStandardEncryption) { return(_CreateHashAlgorithm()); } var node = ei.keyDataNode; var name = node.GetAttribute("hashAlgorithm"); return(_CreateHashAlgorithm(name)); }
private static byte[] _MakeStandardEncryptionKey( HashAlgorithm hAlg, _EncryptionInfo ei, byte[] hFinalPrev, byte[] blockKey) { var hFinal = _H(hAlg, hFinalPrev, blockKey); var x1 = _MakeX1(hAlg, hFinal); var x2 = _MakeX2(hAlg, hFinal); var x3 = _MakeX3(x1, x2); var cbRequiredKeyLength = ei.keyBits / 8; System.Array.Resize(ref x3, (int)cbRequiredKeyLength); return(x3); }
SymmetricAlgorithm _CreateCipherAlgorithmForData(_EncryptionInfo ei) { SymmetricAlgorithm cAlg = null; if (ei.isStandardEncryption) { cAlg = _CreateCipherAlgorithm(); cAlg.KeySize = (int)ei.keyBits; cAlg.Mode = CipherMode.ECB; cAlg.Padding = PaddingMode.None; return(cAlg); } return(_CreateCipherAlgorithm(ei.keyDataNode)); }
private static byte[] _MakeAgileEncryptionKey( HashAlgorithm hAlg, _EncryptionInfo ei, byte[] hFinalPrev, byte[] blockKey) { var hFinal = _H(hAlg, hFinalPrev, blockKey); var node = ei.encryptedKeyNode; var keySize = int.Parse(node.GetAttribute("keyBits")) / 8; var n = hFinal.Length; System.Array.Resize(ref hFinal, keySize); for (; n < hFinal.Length; ++n) { hFinal[n] = 0x36; } return(hFinal); }
private static bool _VerifyAgileEncryptionKey( HashAlgorithm hAlg, _EncryptionInfo ei, byte[] hFinalPrev) { var node = ei.encryptedKeyNode; var evi = System.Convert.FromBase64String( node.GetAttribute("encryptedVerifierHashInput") ); var evh = System.Convert.FromBase64String( node.GetAttribute("encryptedVerifierHashValue") ); var cAlg = _CreateCipherAlgorithmForKey(ei); cAlg.IV = _MakeIv(node); var dvi = new byte[evi.Length]; var dvh = new byte[evh.Length]; cAlg.Key = _MakeEncryptionKey(hAlg, ei, hFinalPrev, new byte[] { 0xFE, 0xA7, 0xD2, 0x76, 0x3B, 0x4B, 0x9E, 0x79 } ); using (var dec = cAlg.CreateDecryptor()) { dec.TransformBlock(evi, 0, dvi.Length, dvi, 0); } cAlg.Key = _MakeEncryptionKey(hAlg, ei, hFinalPrev, new byte[] { 0xD7, 0xAA, 0x0F, 0x6D, 0x30, 0x61, 0x34, 0x4E } ); using (var dec = cAlg.CreateDecryptor()) { dec.TransformBlock(evh, 0, dvh.Length, dvh, 0); } cAlg.Clear(); var hv = hAlg.ComputeHash(dvi); for (var n = 0; n < hv.Length; ++n) { if (hv[n] != dvh[n]) { return(false); } } return(true); }
private static IEnumerable <byte[]> _GenerateHFinalPrev( HashAlgorithm hAlg, _EncryptionInfo ei, string password) { byte[] salt; uint spinCount; if (ei.isAgileEncryption) { var node = ei.encryptedKeyNode; salt = System.Convert.FromBase64String( node.GetAttribute("saltValue") ); spinCount = uint.Parse(node.GetAttribute("spinCount")); } else { salt = new byte[16]; var offset = ei.verifierOffset + 4; System.Array.Copy(ei.bytes, offset, salt, 0, salt.Length); spinCount = 50000; } var hInit = _H(hAlg, salt, Encoding.Unicode.GetBytes(password)); var hSize = hAlg.HashSize / 8; var hInput = new byte[4 + hSize]; var hCurr = hInit; for (uint i = 0; i < spinCount; ++i) { hInput[0] = (byte)(i >> 0); hInput[1] = (byte)(i >> 8); hInput[2] = (byte)(i >> 16); hInput[3] = (byte)(i >> 24); System.Array.Copy(hCurr, 0, hInput, 4, hSize); hCurr = hAlg.ComputeHash(hInput); yield return(null); } yield return(hCurr); }