/// <summary>Add a PBE encryption method to the encrypted object.</summary>
 /// <remarks>
 /// The passphrase is encoded to bytes using UTF8 (Encoding.UTF8.GetBytes).
 /// </remarks>
 public void AddMethodUtf8(char[] passPhrase, HashAlgorithmTag s2kDigest)
 {
     DoAddMethod(PgpUtilities.EncodePassPhrase(passPhrase, true), true, s2kDigest);
 }
        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)));
        }
Beispiel #3
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);
            }
        }
Beispiel #4
0
 public PgpSecretKey(int certificationLevel, PgpKeyPair keyPair, string id, SymmetricKeyAlgorithmTag encAlgorithm, HashAlgorithmTag hashAlgorithm, bool utf8PassPhrase, char[] passPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
     : this(certificationLevel, keyPair, id, encAlgorithm, hashAlgorithm, PgpUtilities.EncodePassPhrase(passPhrase, utf8PassPhrase), clearPassPhrase : true, useSha1, hashedPackets, unhashedPackets, rand)
 {
 }
        /// <summary>Return the decrypted input stream, using the passed in passphrase.</summary>
        public Stream GetDataStream(
            char[] passPhrase)
        {
            try
            {
                SymmetricKeyAlgorithmTag keyAlgorithm = keyData.EncAlgorithm;

                KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(
                    keyAlgorithm, keyData.S2k, passPhrase);


                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);
            }
        }
Beispiel #6
0
            private byte[] EncryptSessionInfo(byte[] sessionInfo, SecureRandom random)
            {
                if (pubKey.Algorithm != PublicKeyAlgorithmTag.ECDH)
                {
                    IBufferedCipher c;
                    switch (pubKey.Algorithm)
                    {
                    case PublicKeyAlgorithmTag.RsaEncrypt:
                    case PublicKeyAlgorithmTag.RsaGeneral:
                        c = CipherUtilities.GetCipher("RSA//PKCS1Padding");
                        break;

                    case PublicKeyAlgorithmTag.ElGamalEncrypt:
                    case PublicKeyAlgorithmTag.ElGamalGeneral:
                        c = CipherUtilities.GetCipher("ElGamal/ECB/PKCS1Padding");
                        break;

                    case PublicKeyAlgorithmTag.Dsa:
                        throw new PgpException("Can't use DSA for encryption.");

                    case PublicKeyAlgorithmTag.ECDsa:
                        throw new PgpException("Can't use ECDSA for encryption.");

                    default:
                        throw new PgpException("unknown asymmetric algorithm: " + pubKey.Algorithm);
                    }

                    AsymmetricKeyParameter akp = pubKey.GetKey();
                    c.Init(true, new ParametersWithRandom(akp, random));
                    return(c.DoFinal(sessionInfo));
                }

                ECDHPublicBcpgKey ecKey = (ECDHPublicBcpgKey)pubKey.PublicKeyPacket.Key;

                // Generate the ephemeral key pair
                IAsymmetricCipherKeyPairGenerator gen = GeneratorUtilities.GetKeyPairGenerator("ECDH");

                gen.Init(new ECKeyGenerationParameters(ecKey.CurveOid, random));

                AsymmetricCipherKeyPair ephKp   = gen.GenerateKeyPair();
                ECPrivateKeyParameters  ephPriv = (ECPrivateKeyParameters)ephKp.Private;
                ECPublicKeyParameters   ephPub  = (ECPublicKeyParameters)ephKp.Public;

                ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey.GetKey();
                ECPoint S = pub.Q.Multiply(ephPriv.D).Normalize();

                KeyParameter key = new KeyParameter(Rfc6637Utilities.CreateKey(pubKey.PublicKeyPacket, S));

                IWrapper w = PgpUtilities.CreateWrapper(ecKey.SymmetricKeyAlgorithm);

                w.Init(true, new ParametersWithRandom(key, random));

                byte[] paddedSessionData = PgpPad.PadSessionData(sessionInfo);

                byte[] C  = w.Wrap(paddedSessionData, 0, paddedSessionData.Length);
                byte[] VB = new MPInteger(new BigInteger(1, ephPub.Q.GetEncoded(false))).GetEncoded();

                byte[] rv = new byte[VB.Length + 1 + C.Length];

                Array.Copy(VB, 0, rv, 0, VB.Length);
                rv[VB.Length] = (byte)C.Length;
                Array.Copy(C, 0, rv, VB.Length + 1, C.Length);

                return(rv);
            }
        /// <summary>Return a signature object containing the current signature state.</summary>
        public PgpSignature Generate()
        {
            ISignatureSubpacket[] hPkts = _hashed, unhPkts = _unhashed;
            if (!PacketPresent(_hashed, SignatureSubpacketTag.CreationTime))
            {
                hPkts = InsertSubpacket(hPkts, new SignatureCreationTime(false, DateTime.UtcNow));
            }

            if (!PacketPresent(_hashed, SignatureSubpacketTag.IssuerKeyId) &&
                !PacketPresent(_unhashed, SignatureSubpacketTag.IssuerKeyId))
            {
                unhPkts = InsertSubpacket(unhPkts, new IssuerKeyId(false, _privKey.KeyId));
            }

            const int version = 4;

            byte[] hData;

            try
            {
                using (var hOut = new MemoryStream())
                {
                    for (var i = 0; i != hPkts.Length; i++)
                    {
                        hPkts[i].Encode(hOut);
                    }

                    var data = hOut.ToArray();

                    using (var sOut = new MemoryStream(data.Length + 6))
                    {
                        sOut.WriteByte(version);
                        sOut.WriteByte((byte)_signatureType);
                        sOut.WriteByte((byte)_keyAlgorithm);
                        sOut.WriteByte((byte)_hashAlgorithm);
                        sOut.WriteByte((byte)(data.Length >> 8));
                        sOut.WriteByte((byte)data.Length);
                        sOut.Write(data, 0, data.Length);


                        hData = sOut.ToArray();
                    }
                }
            }
            catch (IOException e)
            {
                throw new PgpException("exception encoding hashed data.", e);
            }

            _sig.BlockUpdate(hData, 0, hData.Length);
            _dig.BlockUpdate(hData, 0, hData.Length);

            hData = new byte[]
            {
                version,
                0xff,
                (byte)(hData.Length >> 24),
                (byte)(hData.Length >> 16),
                (byte)(hData.Length >> 8),
                (byte)hData.Length
            };

            _sig.BlockUpdate(hData, 0, hData.Length);
            _dig.BlockUpdate(hData, 0, hData.Length);

            var sigBytes    = _sig.GenerateSignature();
            var digest      = DigestUtilities.DoFinal(_dig);
            var fingerPrint = new[] { digest[0], digest[1] };

            // an RSA signature
            var isRsa = _keyAlgorithm == PublicKeyAlgorithmTag.RsaSign ||
                        _keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral;

            var sigValues = isRsa
                ? PgpUtilities.RsaSigToMpi(sigBytes)
                : PgpUtilities.DsaSigToMpi(sigBytes);

            return(new PgpSignature(new SignaturePacket(_signatureType, _privKey.KeyId, _keyAlgorithm, _hashAlgorithm, hPkts, unhPkts, fingerPrint, sigValues)));
        }
        /// <summary>Return a signature object containing the current signature state.</summary>
        public PgpSignature Generate()
        {
            SignatureSubpacket[] hPkts = hashed, unhPkts = unhashed;

            if (!packetPresent(hashed, SignatureSubpacketTag.CreationTime))
            {
                hPkts = insertSubpacket(hPkts, new SignatureCreationTime(false, DateTime.UtcNow));
            }

            if (!packetPresent(hashed, SignatureSubpacketTag.IssuerKeyId) &&
                !packetPresent(unhashed, SignatureSubpacketTag.IssuerKeyId))
            {
                unhPkts = insertSubpacket(unhPkts, new IssuerKeyId(false, privKey.KeyId));
            }

            int version = 4;

            byte[] hData;

            try
            {
                MemoryStream hOut = new MemoryStream();

                for (int i = 0; i != hPkts.Length; i++)
                {
                    hPkts[i].Encode(hOut);
                }

                byte[] data = hOut.ToArray();

                MemoryStream sOut = new MemoryStream(data.Length + 6);
                sOut.WriteByte((byte)version);
                sOut.WriteByte((byte)signatureType);
                sOut.WriteByte((byte)keyAlgorithm);
                sOut.WriteByte((byte)hashAlgorithm);
                sOut.WriteByte((byte)(data.Length >> 8));
                sOut.WriteByte((byte)data.Length);
                sOut.Write(data, 0, data.Length);

                hData = sOut.ToArray();
            }
            catch (IOException e)
            {
                throw new PgpException("exception encoding hashed data.", e);
            }

            sig.BlockUpdate(hData, 0, hData.Length);
            dig.BlockUpdate(hData, 0, hData.Length);

            hData = new byte[]
            {
                (byte)version,
                0xff,
                (byte)(hData.Length >> 24),
                (byte)(hData.Length >> 16),
                (byte)(hData.Length >> 8),
                (byte)hData.Length
            };

            sig.BlockUpdate(hData, 0, hData.Length);
            dig.BlockUpdate(hData, 0, hData.Length);

            byte[] sigBytes    = sig.GenerateSignature();
            byte[] digest      = DigestUtilities.DoFinal(dig);
            byte[] fingerPrint = new byte[] { digest[0], digest[1] };

            // an RSA signature
            bool isRsa = keyAlgorithm == PublicKeyAlgorithmTag.RsaSign ||
                         keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral;

            MPInteger[] sigValues = isRsa
                                ?       PgpUtilities.RsaSigToMpi(sigBytes)
                                :       PgpUtilities.DsaSigToMpi(sigBytes);

            return(new PgpSignature(
                       new SignaturePacket(signatureType, privKey.KeyId, keyAlgorithm,
                                           hashAlgorithm, hPkts, unhPkts, fingerPrint, sigValues)));
        }
Beispiel #9
0
 public static PgpSecretKey ParseSecretKeyFromSExprUtf8(Stream inputStream, char[] passPhrase)
 {
     return(DoParseSecretKeyFromSExpr(inputStream, PgpUtilities.EncodePassPhrase(passPhrase, utf8: true), clearPassPhrase: true));
 }
        private byte[] ExtractKeyData(
            char[] passPhrase)
        {
            SymmetricKeyAlgorithmTag encAlgorithm = secret.EncAlgorithm;

            byte[] encData = secret.GetSecretKeyData();

            if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
            {
                // TODO Check checksum here?
                return(encData);
            }

            // TODO Factor this block out as 'decryptData'
            try
            {
                KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(secret.EncAlgorithm, secret.S2k, passPhrase);
                byte[]       iv  = secret.GetIV();
                byte[]       data;

                if (secret.PublicKeyPacket.Version >= 4)
                {
                    data = RecoverKeyData(encAlgorithm, "/CFB/NoPadding", key, iv, encData, 0, encData.Length);

                    bool   useSha1 = secret.S2kUsage == SecretKeyPacket.UsageSha1;
                    byte[] check   = Checksum(useSha1, data, (useSha1) ? data.Length - 20 : data.Length - 2);

                    for (int i = 0; i != check.Length; i++)
                    {
                        if (check[i] != data[data.Length - check.Length + i])
                        {
                            throw new PgpException("Checksum mismatch at " + i + " of " + check.Length);
                        }
                    }
                }
                else // version 2 or 3, RSA only.
                {
                    data = new byte[encData.Length];

                    iv = Arrays.Clone(iv);

                    //
                    // read in the four numbers
                    //
                    int pos = 0;

                    for (int i = 0; i != 4; i++)
                    {
                        int encLen = (((encData[pos] << 8) | (encData[pos + 1] & 0xff)) + 7) / 8;

                        data[pos]     = encData[pos];
                        data[pos + 1] = encData[pos + 1];
                        pos          += 2;

                        byte[] tmp = RecoverKeyData(encAlgorithm, "/CFB/NoPadding", key, iv, encData, pos, encLen);
                        Array.Copy(tmp, 0, data, pos, encLen);
                        pos += encLen;

                        if (i != 3)
                        {
                            Array.Copy(encData, pos - iv.Length, iv, 0, iv.Length);
                        }
                    }

                    //
                    // verify and copy checksum
                    //

                    data[pos]     = encData[pos];
                    data[pos + 1] = encData[pos + 1];

                    int cs     = ((encData[pos] << 8) & 0xff00) | (encData[pos + 1] & 0xff);
                    int calcCs = 0;
                    for (int j = 0; j < pos; j++)
                    {
                        calcCs += data[j] & 0xff;
                    }

                    calcCs &= 0xffff;
                    if (calcCs != cs)
                    {
                        throw new PgpException("Checksum mismatch: passphrase wrong, expected "
                                               + cs.ToString("X")
                                               + " found " + calcCs.ToString("X"));
                    }
                }

                return(data);
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception decrypting key", e);
            }
        }
Beispiel #11
0
 public static PgpSecretKey CopyWithNewPasswordUtf8(PgpSecretKey key, char[] oldPassPhrase, char[] newPassPhrase, SymmetricKeyAlgorithmTag newEncAlgorithm, SecureRandom rand)
 {
     return(DoCopyWithNewPassword(key, PgpUtilities.EncodePassPhrase(oldPassPhrase, utf8: true), PgpUtilities.EncodePassPhrase(newPassPhrase, utf8: true), clearPassPhrase: true, newEncAlgorithm, rand));
 }
Beispiel #12
0
 public PgpPrivateKey ExtractPrivateKeyUtf8(char[] passPhrase)
 {
     return(DoExtractPrivateKey(PgpUtilities.EncodePassPhrase(passPhrase, utf8: true), clearPassPhrase: true));
 }
Beispiel #13
0
        private byte[] ExtractKeyData(byte[] rawPassPhrase, bool clearPassPhrase)
        {
            SymmetricKeyAlgorithmTag encAlgorithm = secret.EncAlgorithm;

            byte[] secretKeyData = secret.GetSecretKeyData();
            if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
            {
                return(secretKeyData);
            }
            try
            {
                KeyParameter key = PgpUtilities.DoMakeKeyFromPassPhrase(secret.EncAlgorithm, secret.S2k, rawPassPhrase, clearPassPhrase);
                byte[]       iV  = secret.GetIV();
                byte[]       array;
                if (secret.PublicKeyPacket.Version >= 4)
                {
                    array = RecoverKeyData(encAlgorithm, "/CFB/NoPadding", key, iV, secretKeyData, 0, secretKeyData.Length);
                    bool   flag   = secret.S2kUsage == 254;
                    byte[] array2 = Checksum(flag, array, flag ? (array.Length - 20) : (array.Length - 2));
                    for (int i = 0; i != array2.Length; i++)
                    {
                        if (array2[i] != array[array.Length - array2.Length + i])
                        {
                            throw new PgpException(string.Concat(new object[4] {
                                "Checksum mismatch at ", i, " of ", array2.Length
                            }));
                        }
                    }
                }
                else
                {
                    array = new byte[secretKeyData.Length];
                    iV    = Arrays.Clone(iV);
                    int num = 0;
                    for (int j = 0; j != 4; j++)
                    {
                        int num2 = (((secretKeyData[num] << 8) | (secretKeyData[num + 1] & 0xFF)) + 7) / 8;
                        array[num]     = secretKeyData[num];
                        array[num + 1] = secretKeyData[num + 1];
                        num           += 2;
                        byte[] array3 = RecoverKeyData(encAlgorithm, "/CFB/NoPadding", key, iV, secretKeyData, num, num2);
                        global::System.Array.Copy((global::System.Array)array3, 0, (global::System.Array)array, num, num2);
                        num += num2;
                        if (j != 3)
                        {
                            global::System.Array.Copy((global::System.Array)secretKeyData, num - iV.Length, (global::System.Array)iV, 0, iV.Length);
                        }
                    }
                    array[num]     = secretKeyData[num];
                    array[num + 1] = secretKeyData[num + 1];
                    int num3 = ((secretKeyData[num] << 8) & 0xFF00) | (secretKeyData[num + 1] & 0xFF);
                    int num4 = 0;
                    for (int k = 0; k < num; k++)
                    {
                        num4 += array[k] & 0xFF;
                    }
                    num4 &= 0xFFFF;
                    if (num4 != num3)
                    {
                        throw new PgpException("Checksum mismatch: passphrase wrong, expected " + num3.ToString("X") + " found " + num4.ToString("X"));
                    }
                }
                return(array);
            }
            catch (PgpException ex)
            {
                throw ex;
            }
            catch (global::System.Exception exception)
            {
                throw new PgpException("Exception decrypting key", exception);
            }
        }
Beispiel #14
0
        /// <summary>Return a signature object containing the current signature state.</summary>
        public PgpSignature Generate()
        {
            MPInteger[]  sigValues;
            int          version = 4;
            MemoryStream sOut    = new MemoryStream();

//            int index = 0;
//
//			if (!creationTimeFound)
//            {
//                hashed[index++] = new SignatureCreationTime(false, DateTime.UtcNow);
//            }
//
//			if (!issuerKeyIDFound)
//            {
//                hashed[index++] = new IssuerKeyId(false, privKey.KeyId);
//            }
            SignatureSubpacket[] hPkts, unhPkts;

            if (!packetPresent(hashed, SignatureSubpacketTag.CreationTime))
            {
                hPkts = insertSubpacket(hashed, new SignatureCreationTime(false, DateTime.UtcNow));
            }
            else
            {
                hPkts = hashed;
            }

            if (!packetPresent(hashed, SignatureSubpacketTag.IssuerKeyId) &&
                !packetPresent(unhashed, SignatureSubpacketTag.IssuerKeyId))
            {
                unhPkts = insertSubpacket(unhashed, new IssuerKeyId(false, privKey.KeyId));
            }
            else
            {
                unhPkts = unhashed;
            }

            try
            {
                sOut.WriteByte((byte)version);
                sOut.WriteByte((byte)signatureType);
                sOut.WriteByte((byte)keyAlgorithm);
                sOut.WriteByte((byte)hashAlgorithm);

                MemoryStream hOut = new MemoryStream();

                for (int i = 0; i != hPkts.Length; i++)
                {
                    hPkts[i].Encode(hOut);
                }

                byte[] data = hOut.ToArray();

                sOut.WriteByte((byte)(data.Length >> 8));
                sOut.WriteByte((byte)data.Length);
                sOut.Write(data, 0, data.Length);
            }
            catch (IOException e)
            {
                throw new PgpException("exception encoding hashed data.", e);
            }

            byte[] hData = sOut.ToArray();

            sig.BlockUpdate(hData, 0, hData.Length);
            dig.BlockUpdate(hData, 0, hData.Length);

            sOut = new MemoryStream();
            sOut.WriteByte((byte)version);
            sOut.WriteByte((byte)0xff);
            sOut.WriteByte((byte)(hData.Length >> 24));
            sOut.WriteByte((byte)(hData.Length >> 16));
            sOut.WriteByte((byte)(hData.Length >> 8));
            sOut.WriteByte((byte)(hData.Length));

            hData = sOut.ToArray();

            sig.BlockUpdate(hData, 0, hData.Length);
            dig.BlockUpdate(hData, 0, hData.Length);

            byte[] sigBytes    = sig.GenerateSignature();
            byte[] digest      = DigestUtilities.DoFinal(dig);
            byte[] fingerPrint = new byte[] { digest[0], digest[1] };

            if (keyAlgorithm == PublicKeyAlgorithmTag.RsaSign ||
                keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral)       // an RSA signature
            {
                sigValues = new MPInteger[] { new MPInteger(new BigInteger(1, sigBytes)) };
            }
            else
            {
                sigValues = PgpUtilities.DsaSigToMpi(sigBytes);
            }

            return(new PgpSignature(
                       new SignaturePacket(signatureType, privKey.KeyId, keyAlgorithm,
                                           hashAlgorithm, hPkts, unhPkts, fingerPrint, sigValues)));
        }
        public PgpSignature Generate()
        {
            //IL_006b: Unknown result type (might be due to invalid IL or missing references)
            //IL_0072: Expected O, but got Unknown
            //IL_009e: Unknown result type (might be due to invalid IL or missing references)
            //IL_00a5: Expected O, but got Unknown
            //IL_010c: Expected O, but got Unknown
            SignatureSubpacket[] array  = hashed;
            SignatureSubpacket[] array2 = unhashed;
            if (!packetPresent(hashed, SignatureSubpacketTag.CreationTime))
            {
                array = insertSubpacket(array, new SignatureCreationTime(critical: false, global::System.DateTime.get_UtcNow()));
            }
            if (!packetPresent(hashed, SignatureSubpacketTag.IssuerKeyId) && !packetPresent(unhashed, SignatureSubpacketTag.IssuerKeyId))
            {
                array2 = insertSubpacket(array2, new IssuerKeyId(critical: false, privKey.KeyId));
            }
            int num = 4;

            byte[] array4;
            try
            {
                MemoryStream val = new MemoryStream();
                for (int i = 0; i != array.Length; i++)
                {
                    array[i].Encode((Stream)(object)val);
                }
                byte[]       array3 = val.ToArray();
                MemoryStream val2   = new MemoryStream(array3.Length + 6);
                ((Stream)val2).WriteByte((byte)num);
                ((Stream)val2).WriteByte((byte)signatureType);
                ((Stream)val2).WriteByte((byte)keyAlgorithm);
                ((Stream)val2).WriteByte((byte)hashAlgorithm);
                ((Stream)val2).WriteByte((byte)(array3.Length >> 8));
                ((Stream)val2).WriteByte((byte)array3.Length);
                ((Stream)val2).Write(array3, 0, array3.Length);
                array4 = val2.ToArray();
            }
            catch (IOException val3)
            {
                IOException exception = val3;
                throw new PgpException("exception encoding hashed data.", (global::System.Exception)(object) exception);
            }
            sig.BlockUpdate(array4, 0, array4.Length);
            dig.BlockUpdate(array4, 0, array4.Length);
            array4 = new byte[6]
            {
                (byte)num,
                255,
                (byte)(array4.Length >> 24),
                (byte)(array4.Length >> 16),
                (byte)(array4.Length >> 8),
                (byte)array4.Length
            };
            sig.BlockUpdate(array4, 0, array4.Length);
            dig.BlockUpdate(array4, 0, array4.Length);
            byte[] encoding    = sig.GenerateSignature();
            byte[] array5      = DigestUtilities.DoFinal(dig);
            byte[] fingerprint = new byte[2]
            {
                array5[0],
                array5[1]
            };
            MPInteger[] signature = ((keyAlgorithm == PublicKeyAlgorithmTag.RsaSign || keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral) ? PgpUtilities.RsaSigToMpi(encoding) : PgpUtilities.DsaSigToMpi(encoding));
            return(new PgpSignature(new SignaturePacket(signatureType, privKey.KeyId, keyAlgorithm, hashAlgorithm, array, array2, fingerprint, signature)));
        }
Beispiel #16
0
        private byte[] ExtractKeyData(
            char[] passPhrase)
        {
            SymmetricKeyAlgorithmTag alg = secret.EncAlgorithm;

            byte[] encData = secret.GetSecretKeyData();

            if (alg == SymmetricKeyAlgorithmTag.Null)
            {
                return(encData);
            }

            byte[]          data;
            IBufferedCipher c = null;

            try
            {
                string cName = PgpUtilities.GetSymmetricCipherName(alg);
                c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding");
            }
            catch (Exception e)
            {
                throw new PgpException("Exception creating cipher", e);
            }

            // TODO Factor this block out as 'encryptData'
            try
            {
                KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(secret.EncAlgorithm, secret.S2k, passPhrase);
                byte[]       iv  = secret.GetIV();

                if (secret.PublicKeyPacket.Version == 4)
                {
                    c.Init(false, new ParametersWithIV(key, iv));

                    data = c.DoFinal(encData);

                    bool   useSha1 = secret.S2kUsage == SecretKeyPacket.UsageSha1;
                    byte[] check   = Checksum(useSha1, data, (useSha1) ? data.Length - 20 : data.Length - 2);

                    for (int i = 0; i != check.Length; i++)
                    {
                        if (check[i] != data[data.Length - check.Length + i])
                        {
                            throw new PgpException("Checksum mismatch at " + i + " of " + check.Length);
                        }
                    }
                }
                else // version 2 or 3, RSA only.
                {
                    data = new byte[encData.Length];

                    //
                    // read in the four numbers
                    //
                    int pos = 0;

                    for (int i = 0; i != 4; i++)
                    {
                        c.Init(false, new ParametersWithIV(key, iv));

                        int encLen = (((encData[pos] << 8) | (encData[pos + 1] & 0xff)) + 7) / 8;

                        data[pos]     = encData[pos];
                        data[pos + 1] = encData[pos + 1];
                        pos          += 2;

                        c.DoFinal(encData, pos, encLen, data, pos);
                        pos += encLen;

                        if (i != 3)
                        {
                            Array.Copy(encData, pos - iv.Length, iv, 0, iv.Length);
                        }
                    }

                    //
                    // verify Checksum
                    //
                    int cs     = ((encData[pos] << 8) & 0xff00) | (encData[pos + 1] & 0xff);
                    int calcCs = 0;
                    for (int j = 0; j < data.Length - 2; j++)
                    {
                        calcCs += data[j] & 0xff;
                    }

                    calcCs &= 0xffff;
                    if (calcCs != cs)
                    {
                        throw new PgpException("Checksum mismatch: passphrase wrong, expected "
                                               + cs.ToString("X")
                                               + " found " + calcCs.ToString("X"));
                    }
                }

                return(data);
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception decrypting key", e);
            }
        }
Beispiel #17
0
        internal PgpSecretKey(
            PgpKeyPair keyPair,
            SymmetricKeyAlgorithmTag encAlgorithm,
            char[]                                              passPhrase,
            bool useSHA1,
            SecureRandom rand)
        {
            PublicKeyPacket pubPk = keyPair.PublicKey.publicPk;

            BcpgObject secKey;

            switch (keyPair.PublicKey.Algorithm)
            {
            case PublicKeyAlgorithmTag.RsaEncrypt:
            case PublicKeyAlgorithmTag.RsaSign:
            case PublicKeyAlgorithmTag.RsaGeneral:
                RsaPrivateCrtKeyParameters rsK = (RsaPrivateCrtKeyParameters)keyPair.PrivateKey.Key;
                secKey = new RsaSecretBcpgKey(rsK.Exponent, rsK.P, rsK.Q);
                break;

            case PublicKeyAlgorithmTag.Dsa:
                DsaPrivateKeyParameters dsK = (DsaPrivateKeyParameters)keyPair.PrivateKey.Key;
                secKey = new DsaSecretBcpgKey(dsK.X);
                break;

            case PublicKeyAlgorithmTag.ElGamalEncrypt:
            case PublicKeyAlgorithmTag.ElGamalGeneral:
                ElGamalPrivateKeyParameters esK = (ElGamalPrivateKeyParameters)keyPair.PrivateKey.Key;
                secKey = new ElGamalSecretBcpgKey(esK.X);
                break;

            default:
                throw new PgpException("unknown key class");
            }

            string cName = PgpUtilities.GetSymmetricCipherName(encAlgorithm);

            IBufferedCipher c = null;

            if (cName != null)
            {
                try
                {
                    c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding");
                }
                catch (Exception e)
                {
                    throw new PgpException("Exception creating cipher", e);
                }
            }

            try
            {
                MemoryStream     bOut = new MemoryStream();
                BcpgOutputStream pOut = new BcpgOutputStream(bOut);

                pOut.WriteObject(secKey);

                byte[] keyData       = bOut.ToArray();
                byte[] checksumBytes = Checksum(useSHA1, keyData, keyData.Length);

                pOut.Write(checksumBytes);

                byte[] bOutData = bOut.ToArray();

                if (c != null)
                {
                    byte[] iv = new byte[8];
                    rand.NextBytes(iv);

                    S2k          s2k = new S2k(HashAlgorithmTag.Sha1, iv, 0x60);
                    KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(encAlgorithm, s2k, passPhrase);

                    iv = new byte[c.GetBlockSize()];
                    rand.NextBytes(iv);
                    c.Init(true, new ParametersWithIV(key, iv));

                    byte[] encData = c.DoFinal(bOutData);

                    int usage = useSHA1
                                                ?       SecretKeyPacket.UsageSha1
                                                :       SecretKeyPacket.UsageChecksum;

                    this.secret = new SecretKeyPacket(pubPk, encAlgorithm, usage, s2k, iv, encData);
                }
                else
                {
                    this.secret = new SecretKeyPacket(pubPk, encAlgorithm, null, null, bOutData);
                }

                this.trust = null;
            }
            catch (PgpException e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception encrypting key", e);
            }

            this.keySigs = new ArrayList();
        }
Beispiel #18
0
 private void GetSig()
 {
     this.sig = SignerUtilities.GetSigner(
         PgpUtilities.GetSignatureName(sigPck.KeyAlgorithm, sigPck.HashAlgorithm));
 }
Beispiel #19
0
        /// <summary>
        /// Return a copy of the passed in secret key, encrypted using a new password
        /// and the passed in algorithm.
        /// </summary>
        /// <param name="key">The PgpSecretKey to be copied.</param>
        /// <param name="oldPassPhrase">The current password for the key.</param>
        /// <param name="newPassPhrase">The new password for the key.</param>
        /// <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param>
        /// <param name="rand">Source of randomness.</param>
        public static PgpSecretKey CopyWithNewPassword(
            PgpSecretKey key,
            char[]                                              oldPassPhrase,
            char[]                                              newPassPhrase,
            SymmetricKeyAlgorithmTag newEncAlgorithm,
            SecureRandom rand)
        {
            byte[] rawKeyData = key.ExtractKeyData(oldPassPhrase);
            int    s2kUsage   = key.secret.S2kUsage;

            byte[] iv  = null;
            S2k    s2k = null;

            byte[] keyData = null;

            if (newEncAlgorithm == SymmetricKeyAlgorithmTag.Null)
            {
                s2kUsage = SecretKeyPacket.UsageNone;
                if (key.secret.S2kUsage == SecretKeyPacket.UsageSha1)                   // SHA-1 hash, need to rewrite Checksum
                {
                    keyData = new byte[rawKeyData.Length - 18];

                    Array.Copy(rawKeyData, 0, keyData, 0, keyData.Length - 2);

                    byte[] check = Checksum(false, keyData, keyData.Length - 2);

                    keyData[keyData.Length - 2] = check[0];
                    keyData[keyData.Length - 1] = check[1];
                }
                else
                {
                    keyData = rawKeyData;
                }
            }
            else
            {
                IBufferedCipher c;
                try
                {
                    string cName = PgpUtilities.GetSymmetricCipherName(newEncAlgorithm);
                    c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding");
                }
                catch (Exception e)
                {
                    throw new PgpException("Exception creating cipher", e);
                }

                iv = new byte[8];
                rand.NextBytes(iv);
                s2k = new S2k(HashAlgorithmTag.Sha1, iv, 0x60);
                try
                {
                    KeyParameter sKey = PgpUtilities.MakeKeyFromPassPhrase(newEncAlgorithm, s2k, newPassPhrase);
                    iv = new byte[c.GetBlockSize()];
                    rand.NextBytes(iv);
                    c.Init(true, new ParametersWithIV(sKey, iv));

                    keyData = c.DoFinal(rawKeyData);
                }
                catch (PgpException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    throw new PgpException("Exception encrypting key", e);
                }
            }

            SecretKeyPacket secret;

            if (key.secret is SecretSubkeyPacket)
            {
                secret = new SecretSubkeyPacket(key.secret.PublicKeyPacket,
                                                newEncAlgorithm, s2kUsage, s2k, iv, keyData);
            }
            else
            {
                secret = new SecretKeyPacket(key.secret.PublicKeyPacket,
                                             newEncAlgorithm, s2kUsage, s2k, iv, keyData);
            }

            if (key.subSigs == null)
            {
                return(new PgpSecretKey(secret, key.trust, key.keySigs, key.ids,
                                        key.idTrusts, key.idSigs, key.pub));
            }

            return(new PgpSecretKey(secret, key.trust, key.subSigs, key.pub));
        }
        /// <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);
            }
        }
        /// <summary>
        /// Gets the data stream.
        /// </summary>
        /// <param name="privKey">The priv key.</param>
        /// <param name="encryptionAlgorithm">The encryption algorithm.</param>
        /// <returns></returns>
        /// <exception cref="Org.BouncyCastle.Bcpg.OpenPgp.PgpException">
        /// exception creating cipher
        /// or
        /// Exception starting decryption
        /// </exception>
        /// <exception cref="System.IO.EndOfStreamException">
        /// unexpected end of stream.
        /// or
        /// unexpected end of stream.
        /// </exception>
        public Stream GetDataStream(IPgpPrivateKey privKey, out SymmetricKeyAlgorithmTag encryptionAlgorithm)
        {
            var plain = this.FetchSymmetricKeyData(privKey);

            encryptionAlgorithm = (SymmetricKeyAlgorithmTag)plain[0];

            IBufferedCipher c2;
            var             cipherName = PgpUtilities.GetSymmetricCipherName(encryptionAlgorithm);
            var             cName      = cipherName;

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

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

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

            try
            {
                var key = ParameterUtilities.CreateKeyParameter(cipherName, plain, 1, plain.Length - 3);
                var iv  = new byte[c2.GetBlockSize()];

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

                this.EncStream = BcpgInputStream.Wrap(new CipherStream(EncData.GetInputStream(), c2, null));
                if (this.EncData is SymmetricEncIntegrityPacket)
                {
                    this.TruncStream = new TruncatedStream(this.EncStream);

                    var digest = DigestUtilities.GetDigest(PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1));
                    EncStream = new DigestStream(TruncStream, digest, null);
                }

                if (Streams.ReadFully(EncStream, iv, 0, iv.Length) < iv.Length)
                {
                    throw new EndOfStreamException("unexpected end of stream.");
                }

                var v1 = this.EncStream.ReadByte();
                var v2 = this.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(this.EncStream);
            }
            catch (PgpException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw new PgpException("Exception starting decryption", e);
            }
        }
Beispiel #22
0
        /// <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);
            }
        }
        public Stream GetDataStream(PgpPrivateKey privKey)
        {
            //IL_012b: Unknown result type (might be due to invalid IL or missing references)
            //IL_015a: Unknown result type (might be due to invalid IL or missing references)
            byte[] array = RecoverSessionData(privKey);
            if (!ConfirmCheckSum(array))
            {
                throw new PgpKeyValidationException("key checksum failed");
            }
            SymmetricKeyAlgorithmTag symmetricKeyAlgorithmTag = (SymmetricKeyAlgorithmTag)array[0];

            if (symmetricKeyAlgorithmTag == SymmetricKeyAlgorithmTag.Null)
            {
                return((Stream)(object)encData.GetInputStream());
            }
            string          symmetricCipherName = PgpUtilities.GetSymmetricCipherName(symmetricKeyAlgorithmTag);
            string          text = symmetricCipherName;
            IBufferedCipher cipher;

            try
            {
                text   = ((!(encData is SymmetricEncIntegrityPacket)) ? (text + "/OpenPGPCFB/NoPadding") : (text + "/CFB/NoPadding"));
                cipher = CipherUtilities.GetCipher(text);
            }
            catch (PgpException ex)
            {
                throw ex;
            }
            catch (global::System.Exception exception)
            {
                throw new PgpException("exception creating cipher", exception);
            }
            try
            {
                KeyParameter parameters = ParameterUtilities.CreateKeyParameter(symmetricCipherName, array, 1, array.Length - 3);
                byte[]       array2     = new byte[cipher.GetBlockSize()];
                cipher.Init(forEncryption: false, new ParametersWithIV(parameters, array2));
                encStream = (Stream)(object)BcpgInputStream.Wrap((Stream)(object)new CipherStream((Stream)(object)encData.GetInputStream(), cipher, null));
                if (encData is SymmetricEncIntegrityPacket)
                {
                    truncStream = new TruncatedStream(encStream);
                    string  digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
                    IDigest digest     = DigestUtilities.GetDigest(digestName);
                    encStream = (Stream)(object)new DigestStream((Stream)(object)truncStream, digest, 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.");
                }
                return(encStream);
            }
            catch (PgpException ex2)
            {
                throw ex2;
            }
            catch (global::System.Exception exception2)
            {
                throw new PgpException("Exception starting decryption", exception2);
            }
        }
Beispiel #24
0
        /// <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);
            }
        }
Beispiel #25
0
 public PgpKeyRingGenerator(int certificationLevel, PgpKeyPair masterKey, string id, SymmetricKeyAlgorithmTag encAlgorithm, HashAlgorithmTag hashAlgorithm, bool utf8PassPhrase, char[] passPhrase, bool useSha1, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, SecureRandom rand)
     : this(certificationLevel, masterKey, id, encAlgorithm, hashAlgorithm, PgpUtilities.EncodePassPhrase(passPhrase, utf8PassPhrase), useSha1, hashedPackets, unhashedPackets, rand)
 {
 }