/// <summary>Create a key pair from a PgpPrivateKey and a PgpPublicKey.</summary> /// <param name="pub">The public key.</param> /// <param name="priv">The private key.</param> public PgpKeyPair( PgpPublicKey pub, PgpPrivateKey priv) { this.pub = pub; this.priv = priv; }
/// <summary>Initialise the generator for signing.</summary> public void InitSign( int sigType, PgpPrivateKey key, SecureRandom random) { this.privKey = key; this.signatureType = sigType; try { ICipherParameters cp = key.Key; if (random != null) { cp = new ParametersWithRandom(key.Key, random); } sig.Init(true, cp); } catch (InvalidKeyException e) { throw new PgpException("invalid key.", e); } dig.Reset(); lastb = 0; }
/// <summary> /// Return the algorithm code for the symmetric algorithm used to encrypt the data. /// </summary> public SymmetricKeyAlgorithmTag GetSymmetricAlgorithm( PgpPrivateKey privKey) { byte[] sessionData = RecoverSessionData(privKey); return((SymmetricKeyAlgorithmTag)sessionData[0]); }
public PgpKeyPair( PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, AsymmetricKeyParameter privKey, DateTime time) { this.pub = new PgpPublicKey(algorithm, pubKey, time); this.priv = new PgpPrivateKey(pub.KeyId, pub.PublicKeyPacket, privKey); }
/// <summary>Initialise the generator for signing.</summary> public void InitSign( int sigType, PgpPrivateKey key) { InitSign(sigType, key, null); }
/// <summary>Return the decrypted data stream for the packet.</summary> public Stream GetDataStream( PgpPrivateKey privKey) { byte[] sessionData = RecoverSessionData(privKey); if (!ConfirmCheckSum(sessionData)) { throw new PgpKeyValidationException("key checksum failed"); } SymmetricKeyAlgorithmTag symmAlg = (SymmetricKeyAlgorithmTag)sessionData[0]; if (symmAlg == SymmetricKeyAlgorithmTag.Null) { return(encData.GetInputStream()); } IBufferedCipher cipher; string cipherName = PgpUtilities.GetSymmetricCipherName(symmAlg); string cName = cipherName; try { if (encData is SymmetricEncIntegrityPacket) { cName += "/CFB/NoPadding"; } else { cName += "/OpenPGPCFB/NoPadding"; } cipher = CipherUtilities.GetCipher(cName); } catch (PgpException e) { throw e; } catch (Exception e) { throw new PgpException("exception creating cipher", e); } try { KeyParameter key = ParameterUtilities.CreateKeyParameter( cipherName, sessionData, 1, sessionData.Length - 3); byte[] iv = new byte[cipher.GetBlockSize()]; cipher.Init(false, new ParametersWithIV(key, iv)); encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), cipher, 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 deemed // a security risk for typical public key encryption usages, // therefore we do not perform the check. // 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 starting decryption", e); } }
private byte[] RecoverSessionData(PgpPrivateKey privKey) { byte[][] secKeyData = keyData.GetEncSessionKey(); if (keyData.Algorithm == PublicKeyAlgorithmTag.ECDH) { ECDHPublicBcpgKey ecKey = (ECDHPublicBcpgKey)privKey.PublicKeyPacket.Key; X9ECParameters x9Params = ECKeyPairGenerator.FindECCurveByOid(ecKey.CurveOid); byte[] enc = secKeyData[0]; int pLen = ((((enc[0] & 0xff) << 8) + (enc[1] & 0xff)) + 7) / 8; byte[] pEnc = new byte[pLen]; Array.Copy(enc, 2, pEnc, 0, pLen); byte[] keyEnc = new byte[enc[pLen + 2]]; Array.Copy(enc, 2 + pLen + 1, keyEnc, 0, keyEnc.Length); ECPoint publicPoint = x9Params.Curve.DecodePoint(pEnc); ECPrivateKeyParameters privKeyParams = (ECPrivateKeyParameters)privKey.Key; ECPoint S = publicPoint.Multiply(privKeyParams.D).Normalize(); KeyParameter key = new KeyParameter(Rfc6637Utilities.CreateKey(privKey.PublicKeyPacket, S)); IWrapper w = PgpUtilities.CreateWrapper(ecKey.SymmetricKeyAlgorithm); w.Init(false, key); return(PgpPad.UnpadSessionData(w.Unwrap(keyEnc, 0, keyEnc.Length))); } IBufferedCipher cipher = GetKeyCipher(keyData.Algorithm); try { cipher.Init(false, privKey.Key); } catch (InvalidKeyException e) { throw new PgpException("error setting asymmetric cipher", e); } if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt || keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral) { byte[] bi = secKeyData[0]; cipher.ProcessBytes(bi, 2, bi.Length - 2); } else { ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key; int size = (k.Parameters.P.BitLength + 7) / 8; ProcessEncodedMpi(cipher, size, secKeyData[0]); ProcessEncodedMpi(cipher, size, secKeyData[1]); } try { return(cipher.DoFinal()); } catch (Exception e) { throw new PgpException("exception decrypting secret key", e); } }