Beispiel #1
0
        /// <summary>
        /// Return a copy of the passed in secret key, encrypted using a new password
        /// and the passed in algorithm.
        /// </summary>
        /// <remarks>
        /// Allows the caller to handle the encoding of the passphrase to bytes.
        /// </remarks>
        /// <param name="key">The PgpSecretKey to be copied.</param>
        /// <param name="rawOldPassPhrase">The current password for the key.</param>
        /// <param name="rawNewPassPhrase">The new password for the key.</param>
        public static PgpSecretKey CopyWithNewPassword(
            PgpSecretKey key,
            ReadOnlySpan <byte> rawOldPassPhrase,
            ReadOnlySpan <byte> rawNewPassPhrase)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }
            if (key.IsPrivateKeyEmpty)
            {
                throw new PgpException("no private key in this SecretKey - public key present only.");
            }

            byte[] rawKeyData = CryptoPool.Rent(key.keyPacket.KeyBytes.Length - key.keyPacket.PublicKeyLength + 0x20);
            try
            {
                S2kBasedEncryption.DecryptSecretKey(
                    rawOldPassPhrase,
                    key.keyPacket.KeyBytes.AsSpan(key.keyPacket.PublicKeyLength),
                    rawKeyData,
                    out int rawKeySize,
                    key.keyPacket.Version);

                // Use the default S2K parameters
                var s2kParameters = new S2kParameters();

                var newKeyData = new byte[S2kBasedEncryption.GetEncryptedLength(s2kParameters, rawKeySize, key.keyPacket.Version) + key.keyPacket.PublicKeyLength];
                key.keyPacket.KeyBytes.AsSpan(0, key.keyPacket.PublicKeyLength).CopyTo(newKeyData);

                S2kBasedEncryption.EncryptSecretKey(
                    rawNewPassPhrase,
                    s2kParameters,
                    rawKeyData.AsSpan(0, rawKeySize),
                    newKeyData.AsSpan(key.keyPacket.PublicKeyLength),
                    key.keyPacket.Version);

                SecretKeyPacket newKeyPacket;
                if (key.keyPacket is SecretSubkeyPacket)
                {
                    newKeyPacket = new SecretSubkeyPacket(key.Algorithm, key.CreationTime, newKeyData);
                }
                else
                {
                    newKeyPacket = new SecretKeyPacket(key.Algorithm, key.CreationTime, newKeyData);
                }

                return(new PgpSecretKey(newKeyPacket, key));
            }
            finally
            {
                CryptoPool.Return(rawKeyData);
            }
        }
Beispiel #2
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>
        public static PgpSecretKey CopyWithNewPassword(
            PgpSecretKey key,
            ReadOnlySpan <char> oldPassPhrase,
            ReadOnlySpan <char> newPassPhrase)
        {
            int oldPassPhraseByteCount = Encoding.UTF8.GetByteCount(oldPassPhrase);
            int newPassPhraseByteCount = Encoding.UTF8.GetByteCount(newPassPhrase);

            byte[] passphraseBuffer = CryptoPool.Rent(oldPassPhraseByteCount + newPassPhraseByteCount);
            try
            {
                Encoding.UTF8.GetBytes(oldPassPhrase, passphraseBuffer);
                Encoding.UTF8.GetBytes(newPassPhrase, passphraseBuffer.AsSpan(oldPassPhraseByteCount));
                return(CopyWithNewPassword(key, passphraseBuffer.AsSpan(0, oldPassPhraseByteCount), passphraseBuffer.AsSpan(oldPassPhraseByteCount, newPassPhraseByteCount)));
            }
            finally
            {
                CryptoPool.Return(passphraseBuffer, oldPassPhraseByteCount + newPassPhraseByteCount);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Return a copy of the passed in secret key ring, with the master key and sub keys encrypted
        /// using a new password and the passed in algorithm.
        /// </summary>
        /// <param name="ring">The <c>PgpSecretKeyRing</c> to be copied.</param>
        /// <param name="oldPassPhrase">The current password for 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 PgpSecretKeyRing CopyWithNewPassword(
            PgpSecretKeyRing ring,
            ReadOnlySpan <char> oldPassPhrase,
            ReadOnlySpan <char> newPassPhrase)
        {
            IList <PgpSecretKey> newKeys = new List <PgpSecretKey>(ring.keys.Count);

            foreach (PgpSecretKey secretKey in ring.GetSecretKeys())
            {
                if (secretKey.IsPrivateKeyEmpty)
                {
                    newKeys.Add(secretKey);
                }
                else
                {
                    newKeys.Add(PgpSecretKey.CopyWithNewPassword(secretKey, oldPassPhrase, newPassPhrase));
                }
            }

            return(new PgpSecretKeyRing(newKeys, ring.extraPubKeys));
        }