public override void Parse(TreeBuilder tree) { S2K = new S2K(); Version = tree.ReadByte("Version"); S2K.SymAlgo = tree.ReadByte("Symmetric Algorithm", SymmetricAlgorithmTypes.Get); byte S2KSpecifier = tree.ReadByte("S2K Specifier", S2KTypes.Get); if (S2KSpecifier != S2KTypes.Salted && S2KSpecifier != S2KTypes.Simple && S2KSpecifier != S2KTypes.IteratedAndSalted) { throw new InvalidDataException("Invalid S2K Specifier"); } S2K.HashAlgorithm = tree.ReadByte("Hash Algorithm", HashAlgorithmTypes.Get); if (S2KSpecifier == S2KTypes.Salted || S2KSpecifier == S2KTypes.IteratedAndSalted) { S2K.Salt = tree.ReadBytes("Salt", 8); if (S2KSpecifier == S2KTypes.IteratedAndSalted) { byte CodedCount = tree.ReadByte("Coded Iteration"); S2K.ByteCount = (16 + (CodedCount & 15)) << ((CodedCount >> 4) + 6); } } if (tree.IsMoreData()) { EncryptedSessionKey = tree.ReadBytes("Encrypted Session Key"); } else { EncryptedSessionKey = null; } }
public bool DecryptS2K(string Password) { byte[] SessionKey = S2K.GetKey(Password); var decryptor = SymmProcess.GetDecryptor(S2K, SessionKey); var BlockSizeBytes = S2K.IV.Length; int EncryptedLength = EncryptedPrivateKey.Length; int BlockFillLength = BlockSizeBytes * ((EncryptedLength / BlockSizeBytes) + 1); byte[] CryptBytes = new byte[BlockFillLength]; Array.Copy(EncryptedPrivateKey, 0, CryptBytes, 0, EncryptedLength); byte[] ClearBytes; using (MemoryStream msDecrypt = new MemoryStream()) { using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Write)) { csDecrypt.Write(CryptBytes, 0, CryptBytes.Length); csDecrypt.Close(); } ClearBytes = msDecrypt.ToArray().SubArray(0, EncryptedLength); } // Validate Decrypted Key int CheckLen = (S2K.S2KUsage == 254) ? 20 : 2; int DataLen = ClearBytes.Length - CheckLen; byte[] CheckSum = ClearBytes.SubArray(DataLen, CheckLen); bool bSuccess; if (CheckLen == 2) { long C = 0; for (int i = 0; i < DataLen; i++) { C += ClearBytes[i]; } C = C % 65536; bSuccess = ((C >> 8) == CheckSum[0] && (C & 0xff) == CheckSum[1]); } else { SHA1Managed sha = new SHA1Managed(); byte[] HashToCompare = sha.ComputeHash(ClearBytes.SubArray(0, DataLen)); bSuccess = HashToCompare.SequenceEqual(CheckSum); } if (bSuccess) { return(SetPrivate(ClearBytes)); } return(false); }
public static ICryptoTransform GetDecryptor(S2K S2k, byte[] SessionKey) { return(GetDecryptor(S2k.SymAlgo, S2k.IV, SessionKey)); //if (S2k.SymAlgo != SymmetricAlgorithmTypes.AES128) // throw new NotImplementedException("Non AES128 not yet implemented"); //int KeySize = SymmetricAlgorithmTypes.GetKeySize(S2k.SymAlgo); //int BlockSizeBytes = S2k.IV.Length; //RijndaelManaged aes = new RijndaelManaged //{ // KeySize = KeySize, // BlockSize = BlockSizeBytes * 8, // FeedbackSize = BlockSizeBytes * 8, // Key = SessionKey, // IV = S2k.IV, // Mode = CipherMode.CFB, // Padding = PaddingMode.None //}; //return aes.CreateDecryptor(); }
public override void Parse(TreeBuilder tree) { base.Parse(tree); bool IsEncrypted = true; tree.SetBookMark(); var S2K = new S2K { S2KUsage = tree.ReadByte() }; if (S2K.S2KUsage == 254 || S2K.S2KUsage == 255) { S2K.SymAlgo = tree.ReadByte("Symmetric Algorithm", SymmetricAlgorithmTypes.Get); byte S2KSpecifier = tree.ReadByte("S2K Specifier", S2KTypes.Get); if (S2KSpecifier != S2KTypes.Salted && S2KSpecifier != S2KTypes.Simple && S2KSpecifier != S2KTypes.IteratedAndSalted) { //tree.AddCalculated("Invalid S2K", S2KSpecifier.ToString()); tree.AddCalculated("Unable to Process", S2KSpecifier.ToString(), ByteBlockType.CalculatedError); return; } S2K.HashAlgorithm = tree.ReadByte("Hash Algorithm", HashAlgorithmTypes.Get); if (S2KSpecifier == S2KTypes.Salted || S2KSpecifier == S2KTypes.IteratedAndSalted) { S2K.Salt = tree.ReadBytes("Salt", 8); if (S2KSpecifier == S2KTypes.IteratedAndSalted) { byte CodedCount = tree.ReadByte("Coded Iteration"); S2K.ByteCount = (16 + (CodedCount & 15)) << ((CodedCount >> 4) + 6); } } int BlockSizeBytes = SymmetricAlgorithmTypes.GetBlockSize(S2K.SymAlgo) / 8; S2K.IV = tree.ReadBytes("IV", BlockSizeBytes); } else { byte SymAlgo = S2K.S2KUsage; S2K.SymAlgo = SymAlgo; if (SymAlgo != 0) { tree.GoToBookMark(); tree.ReadByte("Symmetric Algorithm", SymmetricAlgorithmTypes.Get); int BlockSize = SymmetricAlgorithmTypes.GetBlockSize(SymAlgo) / 8; S2K.IV = tree.ReadBytes("IV", BlockSize); } else { IsEncrypted = false; } } PublicKeyAlgorithm.S2K = S2K; if (IsEncrypted) { byte[] Encrypted = tree.ReadBytes("Encrypted Secret Key"); PublicKeyAlgorithm.EncryptedPrivateKey = Encrypted; tree.CurrentBlock.ProcessBlock += ExtractPrivateKey; SecretKeyNode = tree.CurrentBlock; } else { byte[] ClearBytes = tree.ReadBytes("Unencrypted Secret Key"); var SecBlockClear = PublicKeyAlgorithm.SetPrivate(ClearBytes); tree.AddChild(PublicKeyAlgorithm.GetPrivateByteBlocks()); } }