2014-02-21 35 views
3

编辑:此代码有效。关键文字每次都有所不同,但关键材料是相同的。我更新了下面的代码,从控制台收集用于创建密钥的数据,但没有回显。我可以使用Bouncycastle for C#创建带有密码的可重现的PGP密钥对吗?

我想生成具有通 短语一个LiveCD受PGP密钥对,分发公共密钥,并用它来加密的个人数据 之前,我将它存储在谷歌驱动器,但从来不写私钥 盘。

我意识到我可以直接使用RSA密钥,但我宁愿 有一个易于使用和灵活性的pgp密钥。

当我需要解密数据时,我将再次从livecd启动,并且 重现私钥。

这是我正在使用的代码...它产生的rsa密钥每 时间相同,但pgp密钥出来的不同。我错过了什么?

由于提前,

代码如下:

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

    } 
} 
+0

换句话说,你想要一个** nonrandom ** PGP密钥生成算法。 – Bobson

+0

是的,但显然有足够的熵,它不能比“真正的”随机算法更容易被破解。在生产中,我将使用哈希算法的组合来拉伸种子。只有我会知道他们应用了多少和顺序。 – spectator

+0

不知道BC是否支持这一点,但创建一对RSA密钥似乎合乎逻辑,然后通过设置密钥材料将它们转换为OpenPGP密钥。 –

回答

0

感谢邓肯!

它工作。

即使底层的RSA密钥相同,每次出现PGP密钥的ASCII装甲文本都不相同。

但是我能够生成一个密钥对,使用公钥对文件进行加密,然后生成一个新的密钥对并使用该新私钥来解密文件。

相关问题