質問

EDIT: This code works. The key text is different every time, but the key material is the same. I have updated the code below to collect the data for key creation from the console, without echo.

I would like to generate a Pgp keypair from a livecd with a pass phrase, distribute the public key and use it to encrypt personal data before I store it at Google drive, but never write the private key to disk.

I realize I could just use the RSA key directly, but I would prefer to have a pgp key for ease of use and flexibility.

When I need to decrypt data I would boot from a livecd again and reproduce the private key.

This is the code I am using... It produces the rsa key the same every time, but the pgp keys come out different. What am I missing?

Thanks in advance,

Code follows:

using System;
using System.IO;
using System.Text;
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;

namespace PgpKeyFromPassphrase
{
    class Program
    {
        static void Main()
        {
            string identity = ReadIdentityFromConsole();
            DateTime keyDate = ReadDateFromConsole();
            string passPhrase = ReadPassphraseFromConsole();
            Console.WriteLine("Generating seed and keys.  This will take some time");
            //Hash the passphrasse 50,000 times
            var seed = GenerateSeed(passPhrase);
            //Create the RSA keypair from the seed
            var keys = GenerateRsaKeys(seed);
            //Create PGP secret key from keypair
            var secretKey = GeneratePgpKeys(keyDate, identity, keys);
            //Write armored secret key
            PrintSecretKey(secretKey);
            //Write armored public key
            PrintPublicKey(secretKey);
            Console.WriteLine("Copy the key and press enter to exit the program");
            Console.ReadLine();
        }


        private static string ReadIdentityFromConsole()
        {
            string retVal = null;
            while (retVal == null || retVal.Equals(string.Empty))
            {
                Console.WriteLine("Type a name to be associated with the Key");
                retVal = Console.ReadLine();
            }
            return retVal;
        }

        private static DateTime ReadDateFromConsole()
        {
            DateTime retVal = DateTime.Today;
            while (true)
            {
                Console.WriteLine("Enter the key creation date.  Press enter for today");
                var line = Console.ReadLine();
                if (line == null || line.Equals(string.Empty) || DateTime.TryParse(line, out retVal)) break;
                else Console.WriteLine("Failed to parse date, try again");
            }
            return retVal;
        }

        static string ReadPassphraseFromConsole()
        {
            var pass1 = new StringBuilder();
            var pass2 = new StringBuilder();
            while (pass1.Length == 0 || !pass1.Equals(pass2))
            {
                if (pass1.Length > 0 && pass2.Length > 0 && !pass1.Equals(pass2))
                {
                    pass1 = new StringBuilder();
                    pass2 = new StringBuilder();
                    Console.WriteLine("Passphrases don't match! Try again.");
                }
                Console.WriteLine("type a strong passphrase and hit enter");
                var key = Console.ReadKey(true);
                while (!key.Key.Equals(ConsoleKey.Enter))
                {
                    if (key.Key.Equals(ConsoleKey.Backspace))
                    {
                        if (pass1.Length > 0) pass1.Remove(pass1.Length - 1, 1);
                    }
                    else pass1.Append(key.KeyChar);
                    key = Console.ReadKey(true);
                }
                Console.WriteLine("repeat passphrase and hit enter");
                key = Console.ReadKey(true);
                while (!key.Key.Equals(ConsoleKey.Enter))
                {
                    if (key.Key.Equals(ConsoleKey.Backspace))
                    {
                        if (pass2.Length > 0) pass2.Remove(pass2.Length - 1, 1);
                    }
                    else pass2.Append(key.KeyChar);
                    key = Console.ReadKey(true);
                }
            }
            return pass1.ToString();
        }

        static byte[] GenerateSeed(string passPhrase)
        {
            //Hash the passphrasse 50,000 times
            var passPhraseBytes = new byte[passPhrase.Length * sizeof(char)];
            Buffer.BlockCopy(passPhrase.ToCharArray(), 0, passPhraseBytes, 0, passPhraseBytes.Length);
            var digester = new Sha256Digest();
            var seed = new byte[digester.GetDigestSize()];
            digester.BlockUpdate(seed, 0, seed.Length);
            digester.DoFinal(seed, 0);
            for (var i = 0; i < 49999; i++)
            {
                digester = new Sha256Digest();
                digester.BlockUpdate(seed, 0, seed.Length);
                digester.DoFinal(seed, 0);
            }
            return seed;
        }

        static AsymmetricCipherKeyPair GenerateRsaKeys(byte[] seed)
        {
            var kpg = new RsaKeyPairGenerator();
            kpg.Init(new RsaKeyGenerationParameters(BigInteger.ValueOf(0x13), new SecureRandom(seed), 4096, 8));
            AsymmetricCipherKeyPair keys = kpg.GenerateKeyPair();
            return keys;
        }

        static PgpSecretKey GeneratePgpKeys(DateTime keyDate, string identity, AsymmetricCipherKeyPair keys)
        {
            var secretKey = new PgpSecretKey(PgpSignature.DefaultCertification, PublicKeyAlgorithmTag.RsaGeneral, keys.Public, keys.Private, keyDate, identity, SymmetricKeyAlgorithmTag.Cast5, null, null, null, new SecureRandom());
            return secretKey;
        }

        static void PrintSecretKey(PgpSecretKey secretKey)
        {
            var secretMemStream = new MemoryStream();
            var secretArmoredStream = new ArmoredOutputStream(secretMemStream);
            secretKey.Encode(secretArmoredStream);
            secretArmoredStream.Close();
            var ascPgpSecretKey = Encoding.ASCII.GetString(secretMemStream.ToArray());
            Console.WriteLine(ascPgpSecretKey);
        }

        static void PrintPublicKey(PgpSecretKey secretKey)
        {
            var pubMemStream = new MemoryStream();
            var pubArmoredStream = new ArmoredOutputStream(pubMemStream);
            secretKey.PublicKey.Encode(pubArmoredStream);
            pubArmoredStream.Close();
            var ascPgpPublicKey = Encoding.ASCII.GetString(pubMemStream.ToArray());
            Console.WriteLine(ascPgpPublicKey);
        }

    }
}
役に立ちましたか?

解決

Thanks Duncan!

It worked.

The ASCII armored text that comes out for the PGP keys are different every time even though the underlying RSA keys are the same.

However I was able generate a keypair use the public key to encrypt a file then generate a new keypair and use that new private key to decrypt the file.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top