public IBlockResult Unwrap(byte[] keyData, int offSet, int length)
 {
     return(wrapper.Unwrap(keyData, offSet, length));
 }
Beispiel #2
0
        private byte[] extractKeyData(
            IPbeSecretKeyDecryptorProvider decryptorFactory)
        {
            byte[] encData = secret.GetSecretKeyData();
            byte[] data;
            if (secret.EncAlgorithm != SymmetricKeyAlgorithmTag.Null)
            {
                try
                {
                    if (secret.PublicKeyPacket.Version == 4)
                    {
                        IKeyUnwrapper <PgpPbeKeyEncryptionParameters> unwrapper = decryptorFactory.CreateKeyUnwrapper(new PgpPbeKeyEncryptionParameters(secret.EncAlgorithm, secret.S2k, secret.GetIV()));

                        data = unwrapper.Unwrap(encData, 0, encData.Length).Collect();

                        bool   useSHA1 = secret.S2kUsage == SecretKeyPacket.UsageSha1;
                        byte[] check   = checksum(useSHA1 ? decryptorFactory.CreateDigestFactory(new PgpDigestTypeIdentifier(HashAlgorithmTag.Sha1)) : null, 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.
                    {
                        IKeyUnwrapper <PgpPbeKeyEncryptionParameters> unwrapper = decryptorFactory.CreateKeyUnwrapper(new PgpPbeKeyEncryptionParameters(secret.EncAlgorithm, secret.S2k, secret.GetIV()));

                        data = new byte[encData.Length];

                        byte[] iv = new byte[secret.GetIV().Length];

                        Array.Copy(secret.GetIV(), 0, iv, 0, iv.Length);

                        //
                        // 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];

                            byte[] tmp = unwrapper.Unwrap(encData, pos + 2, encLen).Collect();
                            Array.Copy(tmp, 0, data, pos + 2, tmp.Length);
                            pos += 2 + 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 < 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"));
                        }
                    }
                }
                catch (PgpException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    throw new PgpException("Exception decrypting key", e);
                }
            }
            else
            {
                data = encData;
            }

            return(data);
        }