/// <summary> /// Create an EncryptionInfo object to encrypt a workbook /// </summary> /// <param name="password">The password</param> /// <param name="algID"></param> /// <param name="key">The Encryption key</param> /// <returns></returns> private EncryptionInfoBinary CreateEncryptionInfo(string password, AlgorithmID algID, out byte[] key) { if (algID == AlgorithmID.Flags || algID == AlgorithmID.RC4) { throw (new ArgumentException("algID must be AES128, AES192 or AES256")); } var encryptionInfo = new EncryptionInfoBinary(); encryptionInfo.MajorVersion = 4; encryptionInfo.MinorVersion = 2; encryptionInfo.Flags = Flags.fAES | Flags.fCryptoAPI; //Header encryptionInfo.Header = new EncryptionHeader(); encryptionInfo.Header.AlgID = algID; encryptionInfo.Header.AlgIDHash = AlgorithmHashID.SHA1; encryptionInfo.Header.Flags = encryptionInfo.Flags; encryptionInfo.Header.KeySize = (algID == AlgorithmID.AES128 ? 0x80 : algID == AlgorithmID.AES192 ? 0xC0 : 0x100); encryptionInfo.Header.ProviderType = ProviderType.AES; encryptionInfo.Header.CSPName = "Microsoft Enhanced RSA and AES Cryptographic Provider\0"; encryptionInfo.Header.Reserved1 = 0; encryptionInfo.Header.Reserved2 = 0; encryptionInfo.Header.SizeExtra = 0; //Verifier encryptionInfo.Verifier = new EncryptionVerifier(); encryptionInfo.Verifier.Salt = new byte[16]; var rnd = RandomNumberGenerator.Create(); rnd.GetBytes(encryptionInfo.Verifier.Salt); encryptionInfo.Verifier.SaltSize = 0x10; key = GetPasswordHashBinary(password, encryptionInfo); var verifier = new byte[16]; rnd.GetBytes(verifier); encryptionInfo.Verifier.EncryptedVerifier = EncryptData(key, verifier, true); //AES = 32 Bits encryptionInfo.Verifier.VerifierHashSize = 0x20; var sha = #if COREFX SHA1.Create(); #else new SHA1Managed(); #endif var verifierHash = sha.ComputeHash(verifier); encryptionInfo.Verifier.EncryptedVerifierHash = EncryptData(key, verifierHash, false); return(encryptionInfo); }
internal static bool VerifySignature(SafeCspHandle cspHandle, SafeCspKeyHandle keyHandle, AlgorithmID signatureAlgorithm, AlgorithmID hashAlgorithm, byte[] hashValue, byte[] signature) { Contract.Assert(cspHandle != null && !cspHandle.IsInvalid, "cspHandle != null && !cspHandle.IsInvalid"); Contract.Assert(keyHandle != null && !keyHandle.IsInvalid, "keyHandle != null && !keyHandle.IsInvalid"); Contract.Assert(((AlgorithmClass)signatureAlgorithm & AlgorithmClass.Signature) == AlgorithmClass.Signature, "Invalid signature algorithm"); Contract.Assert(((AlgorithmClass)hashAlgorithm & AlgorithmClass.Hash) == AlgorithmClass.Hash, "Invalid hash algorithm"); Contract.Assert(hashValue != null, "hashValue != null"); Contract.Assert(signature != null, "signature != null"); // CAPI and the CLR have inverse byte orders for signatures, so we need to reverse before verifying byte[] signatureValue = new byte[signature.Length]; Array.Copy(signature, signatureValue, signatureValue.Length); Array.Reverse(signatureValue); using (SafeCspHashHandle hashHandle = CreateHashAlgorithm(cspHandle, hashAlgorithm)) { // Make sure the hash value is the correct size and import it into the CSP if (hashValue.Length != GetHashPropertyInt32(hashHandle, HashProperty.HashSize)) { throw new CryptographicException((int)ErrorCode.BadHash); } SetHashProperty(hashHandle, HashProperty.HashValue, hashValue); // Do the signature verification. A TRUE result means that the signature was valid. A FALSE // result either means an invalid signature or some other error, so we need to check the last // error to see which occured. if (UnsafeNativeMethods.CryptVerifySignature(hashHandle, signatureValue, signatureValue.Length, keyHandle, null, 0)) { return(true); } else { int error = Marshal.GetLastWin32Error(); if (error != (int)ErrorCode.BadSignature) { throw new CryptographicException(error); } return(false); } } }
/// <summary> /// Create an EncryptionInfo object to encrypt a workbook /// </summary> /// <param name="password">The password</param> /// <param name="algID"></param> /// <param name="key">The Encryption key</param> /// <returns></returns> private EncryptionInfo CreateEncryptionInfo(string password, AlgorithmID algID, out byte[] key) { if (algID == AlgorithmID.Flags || algID == AlgorithmID.RC4) { throw(new ArgumentException("algID must be AES128, AES192 or AES256")); } var encryptionInfo = new EncryptionInfo(); encryptionInfo.MajorVersion = 4; encryptionInfo.MinorVersion = 2; encryptionInfo.Flags = Flags.fAES | Flags.fCryptoAPI; //Header encryptionInfo.Header = new EncryptionHeader(); encryptionInfo.Header.AlgID = algID; encryptionInfo.Header.AlgIDHash = AlgorithmHashID.SHA1; encryptionInfo.Header.Flags = encryptionInfo.Flags; encryptionInfo.Header.KeySize = (algID == AlgorithmID.AES128 ? 0x80 : algID == AlgorithmID.AES192 ? 0xC0 : 0x100); encryptionInfo.Header.ProviderType = ProviderType.AES; encryptionInfo.Header.CSPName = "Microsoft Enhanced RSA and AES Cryptographic Provider\0"; encryptionInfo.Header.Reserved1 = 0; encryptionInfo.Header.Reserved2 = 0; encryptionInfo.Header.SizeExtra = 0; //Verifier encryptionInfo.Verifier = new EncryptionVerifier(); encryptionInfo.Verifier.Salt = new byte[16]; var rnd = RandomNumberGenerator.Create(); rnd.GetBytes(encryptionInfo.Verifier.Salt); encryptionInfo.Verifier.SaltSize = 0x10; key = GetPasswordHash(password, encryptionInfo); var verifier = new byte[16]; rnd.GetBytes(verifier); encryptionInfo.Verifier.EncryptedVerifier = EncryptData(key, verifier,true); //AES = 32 Bits encryptionInfo.Verifier.VerifierHashSize = 0x20; SHA1 sha= new SHA1Managed(); var verifierHash = sha.ComputeHash(verifier); encryptionInfo.Verifier.EncryptedVerifierHash = EncryptData(key, verifierHash, false); return encryptionInfo; }
internal static SafeCspHashHandle CreateHashAlgorithm(SafeCspHandle cspHandle, AlgorithmID algorithm) { Contract.Assert(cspHandle != null && !cspHandle.IsInvalid, "cspHandle != null && !cspHandle.IsInvalid"); Contract.Assert(((AlgorithmClass)algorithm & AlgorithmClass.Hash) == AlgorithmClass.Hash, "Invalid hash algorithm"); SafeCspHashHandle hashHandle = null; if (!UnsafeNativeMethods.CryptCreateHash(cspHandle, algorithm, IntPtr.Zero, 0, out hashHandle)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } return(hashHandle); }
internal static extern bool CryptCreateHash(SafeCspHandle hProv, AlgorithmID Algid, IntPtr hKey, // SafeCspKeyHandle int dwFlags, [Out] out SafeCspHashHandle phHash);
internal static bool VerifySignature(SafeCspHandle cspHandle, SafeCspKeyHandle keyHandle, AlgorithmID signatureAlgorithm, AlgorithmID hashAlgorithm, byte[] hashValue, byte[] signature) { Contract.Assert(cspHandle != null && !cspHandle.IsInvalid, "cspHandle != null && !cspHandle.IsInvalid"); Contract.Assert(keyHandle != null && !keyHandle.IsInvalid, "keyHandle != null && !keyHandle.IsInvalid"); Contract.Assert(((AlgorithmClass)signatureAlgorithm & AlgorithmClass.Signature) == AlgorithmClass.Signature, "Invalid signature algorithm"); Contract.Assert(((AlgorithmClass)hashAlgorithm & AlgorithmClass.Hash) == AlgorithmClass.Hash, "Invalid hash algorithm"); Contract.Assert(hashValue != null, "hashValue != null"); Contract.Assert(signature != null, "signature != null"); // CAPI and the CLR have inverse byte orders for signatures, so we need to reverse before verifying byte[] signatureValue = new byte[signature.Length]; Array.Copy(signature, signatureValue, signatureValue.Length); Array.Reverse(signatureValue); using (SafeCspHashHandle hashHandle = CreateHashAlgorithm(cspHandle, hashAlgorithm)) { // Make sure the hash value is the correct size and import it into the CSP if (hashValue.Length != GetHashPropertyInt32(hashHandle, HashProperty.HashSize)) { throw new CryptographicException((int)ErrorCode.BadHash); } SetHashProperty(hashHandle, HashProperty.HashValue, hashValue); // Do the signature verification. A TRUE result means that the signature was valid. A FALSE // result either means an invalid signature or some other error, so we need to check the last // error to see which occured. if (UnsafeNativeMethods.CryptVerifySignature(hashHandle, signatureValue, signatureValue.Length, keyHandle, null, 0)) { return true; } else { int error = Marshal.GetLastWin32Error(); if (error != (int)ErrorCode.BadSignature) { throw new CryptographicException(error); } return false; } } }
internal static SafeCspHashHandle CreateHashAlgorithm(SafeCspHandle cspHandle, AlgorithmID algorithm) { Contract.Assert(cspHandle != null && !cspHandle.IsInvalid, "cspHandle != null && !cspHandle.IsInvalid"); Contract.Assert(((AlgorithmClass)algorithm & AlgorithmClass.Hash) == AlgorithmClass.Hash, "Invalid hash algorithm"); SafeCspHashHandle hashHandle = null; if (!UnsafeNativeMethods.CryptCreateHash(cspHandle, algorithm, IntPtr.Zero, 0, out hashHandle)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } return hashHandle; }