/// <summary> /// Return an output stream which will encrypt the data as it is written to it. /// </summary> protected override IPacketWriter Open() { var writer = base.Open(); if (cOut != null) { throw new InvalidOperationException("generator already in open state"); } // TODO: Do we want compatibility with old PGP? (IDEA + no password iirc) if (methods.Count == 0) { throw new InvalidOperationException("No encryption methods specified"); } var c = PgpUtilities.GetSymmetricAlgorithm(defAlgorithm); if (methods.Count == 1 && methods[0] is PbeMethod) { PbeMethod m = (PbeMethod)methods[0]; c.Key = m.GetKey(); writer.WritePacket(m.GetSessionInfoPacket()); } else { c.GenerateKey(); byte[] sessionInfo = CreateSessionInfo(defAlgorithm, c.Key); foreach (EncMethod m in methods) { writer.WritePacket(m.GetSessionInfoPacket(sessionInfo)); } } try { if (withIntegrityPacket) { pOut = writer.GetPacketStream(new SymmetricEncIntegrityPacket()); } else { pOut = writer.GetPacketStream(new SymmetricEncDataPacket()); } int blockSize = (c.BlockSize + 7) / 8; byte[] inLineIv = new byte[blockSize * 2]; // Aligned to block size RandomNumberGenerator.Fill(inLineIv.AsSpan(0, blockSize)); inLineIv[blockSize] = inLineIv[blockSize - 2]; inLineIv[blockSize + 1] = inLineIv[blockSize - 1]; ICryptoTransform encryptor; c.IV = new byte[blockSize]; if (withIntegrityPacket) { encryptor = c.CreateEncryptor(); } else { encryptor = c.CreateEncryptor(); var encryptedInlineIv = encryptor.TransformFinalBlock(inLineIv, 0, inLineIv.Length); pOut.Write(encryptedInlineIv.AsSpan(0, blockSize + 2)); c.IV = encryptedInlineIv.AsSpan(2, blockSize).ToArray(); encryptor = c.CreateEncryptor(); } Stream myOut = cOut = new CryptoStream(pOut, new ZeroPaddedCryptoTransform(encryptor), CryptoStreamMode.Write); if (withIntegrityPacket) { digest = SHA1.Create(); myOut = digestOut = new CryptoStream(new FilterStream(myOut), digest, CryptoStreamMode.Write); myOut.Write(inLineIv, 0, blockSize + 2); } return(writer.CreateNestedWriter(new WrappedGeneratorStream(myOut, _ => Close()))); } catch (Exception e) { throw new PgpException("Exception creating cipher", e); } }
private Stream Open(Stream outStr, long length, byte[] buffer) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (cOut != null) { throw new InvalidOperationException("generator already in open state"); } if (((global::System.Collections.ICollection)methods).get_Count() == 0) { throw new InvalidOperationException("No encryption methods specified"); } if (outStr == null) { throw new ArgumentNullException("outStr"); } pOut = new BcpgOutputStream(outStr); KeyParameter keyParameter; if (((global::System.Collections.ICollection)methods).get_Count() == 1) { if (methods.get_Item(0) is PbeMethod) { PbeMethod pbeMethod = (PbeMethod)methods.get_Item(0); keyParameter = pbeMethod.GetKey(); } else { keyParameter = PgpUtilities.MakeRandomKey(defAlgorithm, rand); byte[] si = CreateSessionInfo(defAlgorithm, keyParameter); PubMethod pubMethod = (PubMethod)methods.get_Item(0); try { pubMethod.AddSessionInfo(si, rand); } catch (global::System.Exception exception) { throw new PgpException("exception encrypting session key", exception); } } pOut.WritePacket((ContainedPacket)methods.get_Item(0)); } else { keyParameter = PgpUtilities.MakeRandomKey(defAlgorithm, rand); byte[] si2 = CreateSessionInfo(defAlgorithm, keyParameter); for (int i = 0; i != ((global::System.Collections.ICollection)methods).get_Count(); i++) { EncMethod encMethod = (EncMethod)methods.get_Item(i); try { encMethod.AddSessionInfo(si2, rand); } catch (global::System.Exception exception2) { throw new PgpException("exception encrypting session key", exception2); } pOut.WritePacket(encMethod); } } string symmetricCipherName = PgpUtilities.GetSymmetricCipherName(defAlgorithm); if (symmetricCipherName == null) { throw new PgpException("null cipher specified"); } try { symmetricCipherName = ((!withIntegrityPacket) ? (symmetricCipherName + "/OpenPGPCFB/NoPadding") : (symmetricCipherName + "/CFB/NoPadding")); c = CipherUtilities.GetCipher(symmetricCipherName); byte[] iv = new byte[c.GetBlockSize()]; c.Init(forEncryption: true, new ParametersWithRandom(new ParametersWithIV(keyParameter, iv), rand)); if (buffer == null) { if (withIntegrityPacket) { pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, length + c.GetBlockSize() + 2 + 1 + 22); ((Stream)pOut).WriteByte((byte)1); } else { pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, length + c.GetBlockSize() + 2, oldFormat); } } else if (withIntegrityPacket) { pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, buffer); ((Stream)pOut).WriteByte((byte)1); } else { pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, buffer); } int blockSize = c.GetBlockSize(); byte[] array = new byte[blockSize + 2]; rand.NextBytes(array, 0, blockSize); global::System.Array.Copy((global::System.Array)array, array.Length - 4, (global::System.Array)array, array.Length - 2, 2); Stream val = (Stream)(object)(cOut = new CipherStream((Stream)(object)pOut, null, c)); if (withIntegrityPacket) { string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1); IDigest digest = DigestUtilities.GetDigest(digestName); val = (Stream)(object)(digestOut = new DigestStream(val, null, digest)); } val.Write(array, 0, array.Length); return((Stream)(object)new WrappedGeneratorStream(this, val)); } catch (global::System.Exception exception3) { throw new PgpException("Exception creating cipher", exception3); } }
/// <summary> /// <p> /// If buffer is non null stream assumed to be partial, otherwise the length will be used /// to output a fixed length packet. /// </p> /// <p> /// The stream created can be closed off by either calling Close() /// on the stream or Close() on the generator. Closing the returned /// stream does not close off the Stream parameter <c>outStr</c>. /// </p> /// </summary> private Stream Open( Stream outStr, long length, byte[] buffer) { if (cOut != null) { throw new InvalidOperationException("generator already in open state"); } if (methods.Count == 0) { throw new InvalidOperationException("No encryption methods specified"); } if (outStr == null) { throw new ArgumentNullException("outStr"); } pOut = new BcpgOutputStream(outStr); KeyParameter key; if (methods.Count == 1) { if (methods[0] is PbeMethod) { PbeMethod m = (PbeMethod)methods[0]; key = m.GetKey(); } else { key = PgpUtilities.MakeRandomKey(defAlgorithm, rand); byte[] sessionInfo = CreateSessionInfo(defAlgorithm, key); PubMethod m = (PubMethod)methods[0]; try { m.AddSessionInfo(sessionInfo, rand); } catch (Exception e) { throw new PgpException("exception encrypting session key", e); } } pOut.WritePacket((ContainedPacket)methods[0]); } else // multiple methods { key = PgpUtilities.MakeRandomKey(defAlgorithm, rand); byte[] sessionInfo = CreateSessionInfo(defAlgorithm, key); for (int i = 0; i != methods.Count; i++) { EncMethod m = (EncMethod)methods[i]; try { m.AddSessionInfo(sessionInfo, rand); } catch (Exception e) { throw new PgpException("exception encrypting session key", e); } pOut.WritePacket(m); } } string cName = PgpUtilities.GetSymmetricCipherName(defAlgorithm); if (cName == null) { throw new PgpException("null cipher specified"); } try { if (withIntegrityPacket) { cName += "/CFB/NoPadding"; } else { cName += "/OpenPGPCFB/NoPadding"; } c = CipherUtilities.GetCipher(cName); // TODO Confirm the IV should be all zero bytes (not inLineIv - see below) byte[] iv = new byte[c.GetBlockSize()]; c.Init(true, new ParametersWithRandom(new ParametersWithIV(key, iv), rand)); if (buffer == null) { // // we have to Add block size + 2 for the Generated IV and + 1 + 22 if integrity protected // if (withIntegrityPacket) { pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, length + c.GetBlockSize() + 2 + 1 + 22); pOut.WriteByte(1); // version number } else { pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, length + c.GetBlockSize() + 2, oldFormat); } } else { if (withIntegrityPacket) { pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, buffer); pOut.WriteByte(1); // version number } else { pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, buffer); } } int blockSize = c.GetBlockSize(); byte[] inLineIv = new byte[blockSize + 2]; rand.NextBytes(inLineIv, 0, blockSize); Array.Copy(inLineIv, inLineIv.Length - 4, inLineIv, inLineIv.Length - 2, 2); Stream myOut = cOut = new CipherStream(pOut, null, c); if (withIntegrityPacket) { string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1); IDigest digest = DigestUtilities.GetDigest(digestName); myOut = digestOut = new DigestStream(myOut, null, digest); } myOut.Write(inLineIv, 0, inLineIv.Length); return(new WrappedGeneratorStream(this, myOut)); } catch (Exception e) { throw new PgpException("Exception creating cipher", e); } }
private Stream Open(Stream outStr, long length, byte[] buffer) { if (cOut != null) { throw new InvalidOperationException("generator already in open state"); } if (methods.Count == 0) { throw new InvalidOperationException("No encryption methods specified"); } if (outStr == null) { throw new ArgumentNullException("outStr"); } pOut = new BcpgOutputStream(outStr); KeyParameter keyParameter; if (methods.Count == 1) { if (methods[0] is PbeMethod) { PbeMethod pbeMethod = (PbeMethod)methods[0]; keyParameter = pbeMethod.GetKey(); } else { keyParameter = PgpUtilities.MakeRandomKey(defAlgorithm, rand); byte[] si = CreateSessionInfo(defAlgorithm, keyParameter); PubMethod pubMethod = (PubMethod)methods[0]; try { pubMethod.AddSessionInfo(si, rand); } catch (Exception exception) { throw new PgpException("exception encrypting session key", exception); } } pOut.WritePacket((ContainedPacket)methods[0]); } else { keyParameter = PgpUtilities.MakeRandomKey(defAlgorithm, rand); byte[] si2 = CreateSessionInfo(defAlgorithm, keyParameter); for (int i = 0; i != methods.Count; i++) { EncMethod encMethod = (EncMethod)methods[i]; try { encMethod.AddSessionInfo(si2, rand); } catch (Exception exception2) { throw new PgpException("exception encrypting session key", exception2); } pOut.WritePacket(encMethod); } } string symmetricCipherName = PgpUtilities.GetSymmetricCipherName(defAlgorithm); if (symmetricCipherName == null) { throw new PgpException("null cipher specified"); } try { symmetricCipherName = ((!withIntegrityPacket) ? (symmetricCipherName + "/OpenPGPCFB/NoPadding") : (symmetricCipherName + "/CFB/NoPadding")); c = CipherUtilities.GetCipher(symmetricCipherName); byte[] iv = new byte[c.GetBlockSize()]; c.Init(forEncryption: true, new ParametersWithRandom(new ParametersWithIV(keyParameter, iv), rand)); if (buffer == null) { if (withIntegrityPacket) { pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, length + c.GetBlockSize() + 2 + 1 + 22); pOut.WriteByte(1); } else { pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, length + c.GetBlockSize() + 2, oldFormat); } } else if (withIntegrityPacket) { pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, buffer); pOut.WriteByte(1); } else { pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, buffer); } int blockSize = c.GetBlockSize(); byte[] array = new byte[blockSize + 2]; rand.NextBytes(array, 0, blockSize); Array.Copy(array, array.Length - 4, array, array.Length - 2, 2); Stream stream = cOut = new CipherStream(pOut, null, c); if (withIntegrityPacket) { string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1); IDigest digest = DigestUtilities.GetDigest(digestName); stream = (digestOut = new DigestStream(stream, null, digest)); } stream.Write(array, 0, array.Length); return(new WrappedGeneratorStream(this, stream)); } catch (Exception exception3) { throw new PgpException("Exception creating cipher", exception3); } }