internal void DoAddMethod(byte[] rawPassPhrase, bool clearPassPhrase, HashAlgorithmTag s2kDigest) { S2k s2k = PgpUtilities.GenerateS2k(s2kDigest, 0x60, rand); methods.Add(new PbeMethod(defAlgorithm, s2k, PgpUtilities.DoMakeKeyFromPassPhrase(defAlgorithm, s2k, rawPassPhrase, clearPassPhrase))); }
internal Stream DoGetDataStream(byte[] rawPassPhrase, bool clearPassPhrase) { try { SymmetricKeyAlgorithmTag keyAlgorithm = keyData.EncAlgorithm; KeyParameter key = PgpUtilities.DoMakeKeyFromPassPhrase( keyAlgorithm, keyData.S2k, rawPassPhrase, clearPassPhrase); byte[] secKeyData = keyData.GetSecKeyData(); if (secKeyData != null && secKeyData.Length > 0) { IBufferedCipher keyCipher = CipherUtilities.GetCipher( PgpUtilities.GetSymmetricCipherName(keyAlgorithm) + "/CFB/NoPadding"); keyCipher.Init(false, new ParametersWithIV(key, new byte[keyCipher.GetBlockSize()])); byte[] keyBytes = keyCipher.DoFinal(secKeyData); keyAlgorithm = (SymmetricKeyAlgorithmTag)keyBytes[0]; key = ParameterUtilities.CreateKeyParameter( PgpUtilities.GetSymmetricCipherName(keyAlgorithm), keyBytes, 1, keyBytes.Length - 1); } IBufferedCipher c = CreateStreamCipher(keyAlgorithm); byte[] iv = new byte[c.GetBlockSize()]; c.Init(false, new ParametersWithIV(key, iv)); encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c, null)); if (encData is SymmetricEncIntegrityPacket) { truncStream = new TruncatedStream(encStream); string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1); IDigest digest = DigestUtilities.GetDigest(digestName); encStream = new DigestStream(truncStream, digest, null); } if (Streams.ReadFully(encStream, iv, 0, iv.Length) < iv.Length) { throw new EndOfStreamException("unexpected end of stream."); } int v1 = encStream.ReadByte(); int v2 = encStream.ReadByte(); if (v1 < 0 || v2 < 0) { throw new EndOfStreamException("unexpected end of stream."); } // Note: the oracle attack on the "quick check" bytes is not deemed // a security risk for PBE (see PgpPublicKeyEncryptedData) bool repeatCheckPassed = iv[iv.Length - 2] == (byte)v1 && iv[iv.Length - 1] == (byte)v2; // Note: some versions of PGP appear to produce 0 for the extra // bytes rather than repeating the two previous bytes bool zeroesCheckPassed = v1 == 0 && v2 == 0; if (!repeatCheckPassed && !zeroesCheckPassed) { throw new PgpDataValidationException("quick check failed."); } return(encStream); } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("Exception creating cipher", e); } }