/// <summary>Disposes of the object</summary> protected override void Dispose(bool disposing) #endif { _block = -1; _salt = new byte[8]; _iterations = 1; _hashAlgo.Clear(); }
/// <summary> /// Dispose of all contained resources. /// </summary> public void Dispose() { if (m_decryptionBulkAlgorithm != null) { #if NET40 m_decryptionBulkAlgorithm.Dispose(); #else m_decryptionBulkAlgorithm.Clear(); #endif m_decryptionBulkAlgorithm = null; } if (m_encryptionBulkAlgorithm != null) { #if NET40 m_encryptionBulkAlgorithm.Dispose(); #else m_encryptionBulkAlgorithm.Clear(); #endif m_encryptionBulkAlgorithm = null; } if (m_decryptionHMAC != null) { #if NET40 m_decryptionHMAC.Dispose(); #else m_decryptionHMAC.Clear(); #endif m_decryptionHMAC = null; } if (m_encryptionHMAC != null) { #if NET40 m_encryptionHMAC.Dispose(); #else m_encryptionHMAC.Clear(); #endif m_encryptionHMAC = null; } if (PRF != null) { PRF.Dispose(); PRF = null; } }
private static void VerifyIntegrity(FileData fileData) { BlobBuilder builder = new BlobBuilder(); if (fileData.ppkFileVersion != Version.V1) { builder.AddStringBlob(fileData.publicKeyAlgorithm.GetIdentifierString()); builder.AddStringBlob(fileData.privateKeyAlgorithm.GetIdentifierString()); builder.AddBlob(Encoding.GetEncoding(1252).GetBytes(fileData.comment)); builder.AddBlob(fileData.publicKeyBlob); builder.AddInt(fileData.privateKeyBlob.Data.Length); } builder.AddBytes(fileData.privateKeyBlob.Data); byte[] computedHash; SHA1 sha = SHA1.Create(); if (fileData.isHMAC) { HMAC hmac = HMACSHA1.Create(); if (fileData.passphrase != null) { using (PinnedArray <byte> hashData = new PinnedArray <byte>(cMACKeySalt.Length + fileData.passphrase.Length)) { Array.Copy(Encoding.UTF8.GetBytes(cMACKeySalt), hashData.Data, cMACKeySalt.Length); IntPtr passphrasePtr = Marshal.SecureStringToGlobalAllocUnicode(fileData.passphrase); for (int i = 0; i < fileData.passphrase.Length; i++) { int unicodeChar = Marshal.ReadInt16(passphrasePtr + i * 2); byte ansiChar = Util.UnicodeToAnsi(unicodeChar); hashData.Data[cMACKeySalt.Length + i] = ansiChar; Marshal.WriteByte(passphrasePtr, i * 2, 0); } Marshal.ZeroFreeGlobalAllocUnicode(passphrasePtr); hmac.Key = sha.ComputeHash(hashData.Data); } } else { hmac.Key = sha.ComputeHash(Encoding.UTF8.GetBytes(cMACKeySalt)); } computedHash = hmac.ComputeHash(builder.GetBlob()); hmac.Clear(); } else { computedHash = sha.ComputeHash(builder.GetBlob()); } sha.Clear(); builder.Clear(); try { int macLength = computedHash.Length; bool failed = false; if (fileData.privateMAC.Length == macLength) { for (int i = 0; i < macLength; i++) { if (fileData.privateMAC[i] != computedHash[i]) { failed = true; break; } } } else { failed = true; } if (failed) { // private key data should start with 3 bytes with value 0 if it was // properly decrypted or does not require decryption if ((fileData.privateKeyBlob.Data[0] == 0) && (fileData.privateKeyBlob.Data[1] == 0) && (fileData.privateKeyBlob.Data[2] == 0)) { // so if they bytes are there, passphrase decrypted properly and // something else is wrong with the file contents throw new PpkFormatterException(PpkFormatterException.PpkErrorType.FileCorrupt); } else { // if the bytes are not zeros, we assume that the data was not // properly decrypted because the passphrase was incorrect. throw new PpkFormatterException(PpkFormatterException.PpkErrorType.BadPassphrase); } } } catch { throw; } finally { Array.Clear(computedHash, 0, computedHash.Length); } }