PgpPbeEncryptedData
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.IO;
using System;
using System.IO;
namespace Org.BouncyCastle.Bcpg.OpenPgp
{
public class PgpPbeEncryptedData : PgpEncryptedData
{
private readonly SymmetricKeyEncSessionPacket keyData;
internal PgpPbeEncryptedData(SymmetricKeyEncSessionPacket keyData, InputStreamPacket encData)
: base(encData)
{
this.keyData = keyData;
}
public override Stream GetInputStream()
{
return encData.GetInputStream();
}
public Stream GetDataStream(char[] passPhrase)
{
return DoGetDataStream(PgpUtilities.EncodePassPhrase(passPhrase, false), true);
}
public Stream GetDataStreamUtf8(char[] passPhrase)
{
return DoGetDataStream(PgpUtilities.EncodePassPhrase(passPhrase, true), true);
}
public Stream GetDataStreamRaw(byte[] rawPassPhrase)
{
return DoGetDataStream(rawPassPhrase, false);
}
internal Stream DoGetDataStream(byte[] rawPassPhrase, bool clearPassPhrase)
{
try {
SymmetricKeyAlgorithmTag symmetricKeyAlgorithmTag = keyData.EncAlgorithm;
KeyParameter parameters = PgpUtilities.DoMakeKeyFromPassPhrase(symmetricKeyAlgorithmTag, keyData.S2k, rawPassPhrase, clearPassPhrase);
byte[] secKeyData = keyData.GetSecKeyData();
if (secKeyData != null && secKeyData.Length != 0) {
IBufferedCipher cipher = CipherUtilities.GetCipher(PgpUtilities.GetSymmetricCipherName(symmetricKeyAlgorithmTag) + "/CFB/NoPadding");
cipher.Init(false, new ParametersWithIV(parameters, new byte[cipher.GetBlockSize()]));
byte[] array = cipher.DoFinal(secKeyData);
symmetricKeyAlgorithmTag = (SymmetricKeyAlgorithmTag)array[0];
parameters = ParameterUtilities.CreateKeyParameter(PgpUtilities.GetSymmetricCipherName(symmetricKeyAlgorithmTag), array, 1, array.Length - 1);
}
IBufferedCipher bufferedCipher = CreateStreamCipher(symmetricKeyAlgorithmTag);
byte[] array2 = new byte[bufferedCipher.GetBlockSize()];
bufferedCipher.Init(false, new ParametersWithIV(parameters, array2));
encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), bufferedCipher, null));
if (encData is SymmetricEncIntegrityPacket) {
truncStream = new TruncatedStream(encStream);
IDigest readDigest = PgpUtilities.CreateDigest(HashAlgorithmTag.Sha1);
encStream = new DigestStream(truncStream, readDigest, null);
}
if (Streams.ReadFully(encStream, array2, 0, array2.Length) < array2.Length)
throw new EndOfStreamException("unexpected end of stream.");
int num = encStream.ReadByte();
int num2 = encStream.ReadByte();
if (num < 0 || num2 < 0)
throw new EndOfStreamException("unexpected end of stream.");
bool num3 = array2[array2.Length - 2] == (byte)num && array2[array2.Length - 1] == (byte)num2;
bool flag = num == 0 && num2 == 0;
if (!num3 && !flag)
throw new PgpDataValidationException("quick check failed.");
return encStream;
} catch (PgpException) {
throw;
} catch (Exception innerException) {
throw new PgpException("Exception creating cipher", innerException);
}
}
private IBufferedCipher CreateStreamCipher(SymmetricKeyAlgorithmTag keyAlgorithm)
{
string str = (encData is SymmetricEncIntegrityPacket) ? "CFB" : "OpenPGPCFB";
return CipherUtilities.GetCipher(PgpUtilities.GetSymmetricCipherName(keyAlgorithm) + "/" + str + "/NoPadding");
}
}
}