private byte[] RecoverSessionData(PgpPrivateKey privKey)
        {
            byte[][] encSessionKey = keyData.GetEncSessionKey();
            if (keyData.Algorithm == PublicKeyAlgorithmTag.EC)
            {
                ECDHPublicBcpgKey eCDHPublicBcpgKey = (ECDHPublicBcpgKey)privKey.PublicKeyPacket.Key;
                X9ECParameters    x9ECParameters    = ECKeyPairGenerator.FindECCurveByOid(eCDHPublicBcpgKey.CurveOid);
                byte[]            array             = encSessionKey[0];
                int    num    = (((array[0] & 0xFF) << 8) + (array[1] & 0xFF) + 7) / 8;
                byte[] array2 = new byte[num];
                global::System.Array.Copy((global::System.Array)array, 2, (global::System.Array)array2, 0, num);
                byte[] array3 = new byte[array[num + 2]];
                global::System.Array.Copy((global::System.Array)array, 2 + num + 1, (global::System.Array)array3, 0, array3.Length);
                ECPoint eCPoint = x9ECParameters.Curve.DecodePoint(array2);
                ECPrivateKeyParameters eCPrivateKeyParameters = (ECPrivateKeyParameters)privKey.Key;
                ECPoint      s          = eCPoint.Multiply(eCPrivateKeyParameters.D).Normalize();
                KeyParameter parameters = new KeyParameter(Rfc6637Utilities.CreateKey(privKey.PublicKeyPacket, s));
                IWrapper     wrapper    = PgpUtilities.CreateWrapper(eCDHPublicBcpgKey.SymmetricKeyAlgorithm);
                wrapper.Init(forWrapping: false, parameters);
                return(PgpPad.UnpadSessionData(wrapper.Unwrap(array3, 0, array3.Length)));
            }
            IBufferedCipher keyCipher = GetKeyCipher(keyData.Algorithm);

            try
            {
                keyCipher.Init(forEncryption: false, privKey.Key);
            }
            catch (InvalidKeyException exception)
            {
                throw new PgpException("error setting asymmetric cipher", exception);
            }
            if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt || keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
            {
                byte[] array4 = encSessionKey[0];
                keyCipher.ProcessBytes(array4, 2, array4.Length - 2);
            }
            else
            {
                ElGamalPrivateKeyParameters elGamalPrivateKeyParameters = (ElGamalPrivateKeyParameters)privKey.Key;
                int size = (elGamalPrivateKeyParameters.Parameters.P.BitLength + 7) / 8;
                ProcessEncodedMpi(keyCipher, size, encSessionKey[0]);
                ProcessEncodedMpi(keyCipher, size, encSessionKey[1]);
            }
            try
            {
                return(keyCipher.DoFinal());
            }
            catch (global::System.Exception exception2)
            {
                throw new PgpException("exception decrypting secret key", exception2);
            }
        }
        private byte[] FetchSymmetricKeyData(IPgpPrivateKey privKey)
        {
            byte[] plain;
            var    keyD = _keyData.GetEncSessionKey();

            if (_keyData.Algorithm == PublicKeyAlgorithmTag.Ecdh)
            {
                plain = this.ProcessSymmetricKeyDataForEcdh(privKey, keyD);
            }
            else
            {
                var c1 = GetKeyCipher(_keyData.Algorithm);
                try
                {
                    c1.Init(false, privKey.Key);
                }
                catch (InvalidKeyException e)
                {
                    throw new PgpException("error setting asymmetric cipher", e);
                }

                switch (_keyData.Algorithm)
                {
                case PublicKeyAlgorithmTag.RsaGeneral:
                case PublicKeyAlgorithmTag.RsaEncrypt:
                    this.ProcessSymmetricKeyDataForRsa(c1, keyD);
                    break;

                default:
                    this.ProcessSymmetricKeyDataForElGamal(privKey, c1, keyD);
                    break;
                }

                try
                {
                    plain = c1.DoFinal();
                }
                catch (Exception e)
                {
                    throw new PgpException("exception decrypting secret key", e);
                }
            }

            if (!ConfirmCheckSum(plain))
            {
                throw new PgpKeyValidationException("key checksum failed");
            }

            return(plain);
        }
        private byte[] fetchSymmetricKeyData(
            PgpPrivateKey privKey)
        {
            IBufferedCipher c1 = GetKeyCipher(keyData.Algorithm);

            try
            {
                c1.Init(false, privKey.Key);
            }
            catch (InvalidKeyException e)
            {
                throw new PgpException("error setting asymmetric cipher", e);
            }

            BigInteger[] keyD = keyData.GetEncSessionKey();

            if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt ||
                keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
            {
                c1.ProcessBytes(keyD[0].ToByteArrayUnsigned());
            }
            else
            {
                ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key;
                int size = (k.Parameters.P.BitLength + 7) / 8;

                byte[] bi = keyD[0].ToByteArray();

                int diff = bi.Length - size;
                if (diff >= 0)
                {
                    c1.ProcessBytes(bi, diff, size);
                }
                else
                {
                    byte[] zeros = new byte[-diff];
                    c1.ProcessBytes(zeros);
                    c1.ProcessBytes(bi);
                }

                bi = keyD[1].ToByteArray();

                diff = bi.Length - size;
                if (diff >= 0)
                {
                    c1.ProcessBytes(bi, diff, size);
                }
                else
                {
                    byte[] zeros = new byte[-diff];
                    c1.ProcessBytes(zeros);
                    c1.ProcessBytes(bi);
                }
            }

            byte[] plain;
            try
            {
                plain = c1.DoFinal();
            }
            catch (Exception e)
            {
                throw new PgpException("exception decrypting secret key", e);
            }

            if (!ConfirmCheckSum(plain))
            {
                throw new PgpKeyValidationException("key checksum failed");
            }

            return(plain);
        }
Ejemplo n.º 4
0
        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);
            }
        }
        /// <summary>Return the decrypted data stream for the packet.</summary>
        public Stream GetDataStream(
            PgpPrivateKey privKey)
        {
            IBufferedCipher c1 = GetKeyCipher(keyData.Algorithm);

            try
            {
                c1.Init(false, privKey.Key);
            }
            catch (InvalidKeyException e)
            {
                throw new PgpException("error setting asymmetric cipher", e);
            }

            BigInteger[] keyD = keyData.GetEncSessionKey();

            if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt ||
                keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
            {
                byte[] bi = keyD[0].ToByteArray();

                if (bi[0] == 0)
                {
                    c1.ProcessBytes(bi, 1, bi.Length - 1);
                }
                else
                {
                    c1.ProcessBytes(bi, 0, bi.Length);
                }
            }
            else
            {
                ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key;
                int size = (k.Parameters.P.BitLength + 7) / 8;

                byte[] bi = keyD[0].ToByteArray();

                int diff = bi.Length - size;
                if (diff >= 0)
                {
                    c1.ProcessBytes(bi, diff, size);
                }
                else
                {
                    byte[] zeros = new byte[-diff];
                    c1.ProcessBytes(zeros);
                    c1.ProcessBytes(bi);
                }

                bi = keyD[1].ToByteArray();

                diff = bi.Length - size;
                if (diff >= 0)
                {
                    c1.ProcessBytes(bi, diff, size);
                }
                else
                {
                    byte[] zeros = new byte[-diff];
                    c1.ProcessBytes(zeros);
                    c1.ProcessBytes(bi);
                }
            }

            byte[] plain;
            try
            {
                plain = c1.DoFinal();
            }
            catch (Exception e)
            {
                throw new PgpException("exception decrypting secret key", e);
            }

            if (!ConfirmCheckSum(plain))
            {
                throw new PgpKeyValidationException("key checksum failed");
            }

            IBufferedCipher c2;
            string          cipherName = PgpUtilities.GetSymmetricCipherName((SymmetricKeyAlgorithmTag)plain[0]);
            string          cName      = cipherName;

            try
            {
                if (encData is SymmetricEncIntegrityPacket)
                {
                    cName += "/CFB/NoPadding";
                }
                else
                {
                    cName += "/OpenPGPCFB/NoPadding";
                }

                c2 = CipherUtilities.GetCipher(cName);
            }
//            catch (NoSuchProviderException e)
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("exception creating cipher", e);
            }

            if (c2 == null)
            {
                return(encData.GetInputStream());
            }

            try
            {
                byte[] keyBytes = new byte[plain.Length - 3];
                Array.Copy(plain, 1, keyBytes, 0, keyBytes.Length);

                KeyParameter key = ParameterUtilities.CreateKeyParameter(
                    cipherName, keyBytes);

                byte[] iv = new byte[c2.GetBlockSize()];

                c2.Init(false, new ParametersWithIV(key, iv));

                encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c2, null));

                if (encData is SymmetricEncIntegrityPacket)
                {
                    truncStream = new TruncatedStream(encStream);
                    encStream   = new DigestStream(truncStream,
                                                   DigestUtilities.GetDigest(PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1)), null);
                }

                for (int i = 0; i != iv.Length; i++)
                {
                    int ch = encStream.ReadByte();

                    if (ch < 0)
                    {
                        throw new EndOfStreamException("unexpected end of stream.");
                    }

                    iv[i] = (byte)ch;
                }

                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);
            }
        }