2012-12-05 39 views
2

我创建了一个使用Bouncy Castle 1.47 API生成DSA/El Gamal PGP密钥环的小程序。密钥生成过程非常顺利,没有错误。我用装甲输出导出私钥和公钥到一个文件,当我尝试导入带有GPG生成的私钥(KGpg的是精确的)我收到以下错误:生成带有充气城堡的dsa/elgamal密钥对,无误地导入GPG

[GNUPG:] NODATA 1 
[GNUPG:] IMPORT_OK 17 1277C25B455C71D91EE42C8FF9A6087305C00DA6 
[GNUPG:] IMPORTED F9A6087305C00DA6 [email protected] 
[GNUPG:] IMPORT_OK 1 1277C25B455C71D91EE42C8FF9A6087305C00DA6 
[GNUPG:] IMPORT_RES 1 0 1 0 0 0 0 0 0 1 1 0 0 0 

后,我单击确定它告诉我只有一个密钥已被处理。它看起来只需要DSA密钥,因为它在屏幕上显示为1024/0。

** 编辑 ** 我只是想在Windows上开扩在PGP 10.1.0的钥匙,它也给了我一个错误“钥匙圈包含一个错误的(损坏)PGP包。”

我使用的代码如下所示,第一个是Utility类,第二个是调用它创建密钥的程序。

package george.crypto.pgp; 

import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.security.KeyPair; 
import java.security.KeyPairGenerator; 
import java.security.NoSuchAlgorithmException; 
import java.security.NoSuchProviderException; 
import java.security.Security; 
import java.util.Date; 

import org.bouncycastle.bcpg.ArmoredOutputStream; 
import org.bouncycastle.bcpg.HashAlgorithmTags; 
import org.bouncycastle.jce.provider.BouncyCastleProvider; 
import org.bouncycastle.jce.spec.ElGamalParameterSpec; 
import org.bouncycastle.openpgp.PGPEncryptedData; 
import org.bouncycastle.openpgp.PGPKeyPair; 
import org.bouncycastle.openpgp.PGPKeyRingGenerator; 
import org.bouncycastle.openpgp.PGPPublicKey; 
import org.bouncycastle.openpgp.PGPPublicKeyRing; 
import org.bouncycastle.openpgp.PGPSecretKeyRing; 
import org.bouncycastle.openpgp.PGPSignature; 
import org.bouncycastle.openpgp.operator.PGPDigestCalculator; 
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentSignerBuilder; 
import org.bouncycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder; 
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder; 

public final class PGPTools { 

    static { 
     Security.addProvider(new BouncyCastleProvider()); 
    } 

    private PGPTools() { 

    } 

    public static final void exportSecretKey(PGPKeyRingGenerator pgpKeyRingGen, File keyFile, boolean asciiArmor) throws IOException { 
     PGPSecretKeyRing pgpSecKeyRing = pgpKeyRingGen.generateSecretKeyRing(); 

     if(asciiArmor) { 
      pgpSecKeyRing.encode(new ArmoredOutputStream(new FileOutputStream(keyFile))); 
     } 
     else { 
      pgpSecKeyRing.encode(new FileOutputStream(keyFile)); 
     } 
    } 

    public static final void exportPublicKey(PGPKeyRingGenerator pgpKeyRingGen, File keyFile, boolean asciiArmor) throws IOException { 
     PGPPublicKeyRing pgpPubKeyRing = pgpKeyRingGen.generatePublicKeyRing(); 

     if(asciiArmor) { 
      pgpPubKeyRing.encode(new ArmoredOutputStream(new FileOutputStream(keyFile))); 
     } 
     else { 
      pgpPubKeyRing.encode(new FileOutputStream(keyFile)); 
     } 
    } 

    /** 
    * 
    * @param dsaKeyPair - the generated DSA key pair 
    * @param elGamalKeyPair - the generated El Gamal key pair 
    * @param identity - the given identity of the key pair ring 
    * @param passphrase - the secret pass phrase to protect the key pair 
    * @return a PGP Key Ring Generate with the El Gamal key pair added as sub key 
    * @throws Exception 
    */ 
    @SuppressWarnings("deprecation") 
    public static final PGPKeyRingGenerator createPGPKeyRingGenerator(KeyPair dsaKeyPair, KeyPair elGamalKeyPair, String identity, char[] passphrase) throws Exception 
    { 
     PGPKeyPair dsaPgpKeyPair = new PGPKeyPair(PGPPublicKey.DSA, dsaKeyPair, new Date()); 
     PGPKeyPair elGamalPgpKeyPair = new PGPKeyPair(PGPPublicKey.ELGAMAL_ENCRYPT, elGamalKeyPair, new Date()); 
     PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(HashAlgorithmTags.SHA1); 
     PGPKeyRingGenerator keyRingGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, dsaPgpKeyPair, identity, sha1Calc, null, null, new JcaPGPContentSignerBuilder(dsaPgpKeyPair.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1), new JcePBESecretKeyEncryptorBuilder(PGPEncryptedData.AES_256, sha1Calc).setProvider("BC").build(passphrase)); 
     keyRingGen.addSubKey(elGamalPgpKeyPair); 
     return keyRingGen; 
    } 

    /** 
    * 
    * @param keySize 512 - 1024 (multiple of 64) 
    * @return the DSA generated key pair 
    * @throws NoSuchProviderException 
    * @throws NoSuchAlgorithmException 
    */ 
    public static final KeyPair generateDsaKeyPair(int keySize) throws NoSuchAlgorithmException, NoSuchProviderException 
    { 
     KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA", "BC"); 
     keyPairGenerator.initialize(keySize); 
     KeyPair keyPair = keyPairGenerator.generateKeyPair(); 
     return keyPair; 
    } 

    /** 
    * 
    * @param keySize - 1024, 2048, 4096 
    * @return the El Gamal generated key pair 
    * @throws Exception 
    */ 
    public static final KeyPair generateElGamalKeyPair(int keySize) throws Exception 
    { 
     KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ELGAMAL", "BC"); 
     keyPairGenerator.initialize(keySize); 
     KeyPair keyPair = keyPairGenerator.generateKeyPair(); 
     return keyPair; 
    } 

    /** 
    * 
    * @param paramSpecs - the pre-defined parameter specs 
    * @return the El Gamal generated key pair 
    * @throws Exception 
    */ 
    public static final KeyPair generateElGamalKeyPair(ElGamalParameterSpec paramSpecs) throws Exception 
    { 
     KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("ELGAMAL", "BC"); 
     keyPairGenerator.initialize(paramSpecs); 
     KeyPair keyPair = keyPairGenerator.generateKeyPair(); 
     return keyPair; 
    } 
} 

package george.crypto.pgp; 

import java.io.File; 
import java.math.BigInteger; 
import java.security.KeyPair; 

import org.bouncycastle.jce.spec.ElGamalParameterSpec; 
import org.bouncycastle.openpgp.PGPKeyRingGenerator; 

public class PGPCryptoBC { 

    public PGPCryptoBC() { 
     try { 
      String keysDir = System.getProperty("user.dir")+File.separator+"src/george/crypto/pgp/keys"; 

      //Generating a safe prime is a very long process so it's better to use 
      //a pre-generated safe prime, I took this from http://www.cryptopp.com/fom-serve/cache/71.html 
      BigInteger primeModulous = new BigInteger("36F0255DDE973DCB3B399D747F23E32ED6FDB1F77598338BFDF44159C4EC64DDAEB5F78671CBFB22106AE64C32C5BCE4CFD4F5920DA0EBC8B01ECA9292AE3DBA1B7A4A899DA181390BB3BD1659C81294F400A3490BF9481211C79404A576605A5160DBEE83B4E019B6D799AE131BA4C23DFF83475E9C40FA6725B7C9E3AA2C6596E9C05702DB30A07C9AA2DC235C5269E39D0CA9DF7AAD44612AD6F88F69699298F3CAB1B54367FB0E8B93F735E7DE83CD6FA1B9D1C931C41C6188D3E7F179FC64D87C5D13F85D704A3AA20F90B3AD3621D434096AA7E8E7C66AB683156A951AEA2DD9E76705FAEFEA8D71A5755355970000000000000001", 16); 
      BigInteger baseGenerator = new BigInteger("2", 16); 
      ElGamalParameterSpec paramSpecs = new ElGamalParameterSpec(primeModulous, baseGenerator); 

      KeyPair dsaKeyPair = PGPTools.generateDsaKeyPair(1024); 
      KeyPair elGamalKeyPair = PGPTools.generateElGamalKeyPair(paramSpecs); 
      PGPKeyRingGenerator pgpKeyRingGen = PGPTools.createPGPKeyRingGenerator(dsaKeyPair, elGamalKeyPair, "[email protected]", "TestPass12345!".toCharArray()); 

      PGPTools.exportSecretKey(pgpKeyRingGen, new File(keysDir+File.separator+"secret.asc"), true); 
      PGPTools.exportPublicKey(pgpKeyRingGen, new File(keysDir+File.separator+"public.asc"), true); 
     } 
     catch(Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 

    public static void main(String ... args) { 
     new PGPCryptoBC(); 
    } 
} 

生成的输出是2个文件“secret.asc”和“public.asc”如果我尝试在GPG导入“secret.asc”我得到的错误和El贾迈勒子键不会被导入。

有没有人知道这可能是错误的?

回答

3

我设法解决了我自己的问题。我需要在最后明确地关闭输出流。不这样做会导致数据损坏。

其次,作为额外的奖励,如果我使用rfc3526中列出的安全素数(主模数),它允许我生成不同位长度的El Gamal键。