2016-03-02 40 views
1

我想在Matlab中使用Java生成加密的私钥和CSR。 Matlab增加了一些小的复杂性,但这主要是一个Java问题。我开始用私钥:从Java输出加密的PK8私钥BouncyCastle

java.security.Security.addProvider(org.bouncycastle.jce.provider.BouncyCastleProvider()); 
keyGen = java.security.KeyPairGenerator.getInstance('RSA', 'BC'); 
keyGen.initialize(2048, java.security.SecureRandom()); 
keypair = keyGen.generateKeyPair(); 
privateKey = keypair.getPrivate(); 

如果我加密密钥并将其输出作为PEM:

m=org.bouncycastle.openssl.PKCS8Generator.PBE_SHA1_3DES; 
encryptorBuilder = org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder(m); 
encryptorBuilder.setRandom(java.security.SecureRandom()); 
encryptorBuilder.setPasssword(password); 
oe = encryptorBuilder.build(); 
gen = org.bouncycastle.openssl.jcajce.JcaPKCS8Generator(privateKey,oe); 
privKeyObj = gen.generate(); 
fos = java.io.FileWriter('private.pem'); 
pem = org.bouncycastle.openssl.jcajce.JcaPEMWriter(fos); 
pem.writeObject(privKeyObj); 
pem.flush(); 
fos.close(); 

我得到一个非常好的关键。问题是我想用jdbc来使用密钥,所以我需要一个DER格式化的pk8密钥。我无法弄清楚如何从BouncyCastle中解脱出来。一个成功的kludge解决方法:

textWriter = java.io.StringWriter(); 
pem = org.bouncycastle.openssl.jcajce.JcaPEMWriter(textWriter); 
pem.writeObject(privateKey); 
pem.flush(); 
thekey = char(textWriter.toString()); 
cmd = ['echo "' thekey '"|openssl pkcs8 -topk8 -out private.pk8 -inform PEM -outform DER -passout pass:' password]; 
system(cmd); 

现在,显然这暴露了未加密的私钥和密码。我试过各式各样的东西强迫privKeyObj到DER,但它们通常离开我:

$openssl pkcs8 -inform DER -outform PEM -in private.pk8 -out private.pem 
Error decrypting key 
140735211835472:error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag:tasn_dec.c:1201: 
140735211835472:error:0D06C03A:asn1 encoding routines:ASN1_D2I_EX_PRIMITIVE:nested asn1 error:tasn_dec.c:765: 
140735211835472:error:0D08303A:asn1 encoding routines:ASN1_TEMPLATE_NOEXP_D2I:nested asn1 error:tasn_dec.c:697:Field=version, Type=PKCS8_PRIV_KEY_INFO 

这段代码的目的是生成CSR最终用户的机器上,我再签收,并用机器的MAC地址(和盐)加密,以便程序只能在授权的机器上运行,只有授权的机器才能访问我的PostgreSql数据库。

对此提出建议?

+0

请注意,由于缺少Java和加密标签,我完全错过了这篇文章。始终使用顶级访问标签并指明您的语言。这比使用更具体的更重要:他们基本上是为了让你的问题被其他人注意到。 –

回答

1

我想通了。在我的原始代码中,我使用了BcPKCS12PBEOutputEncryptorBuilder。错误!正确的调用是JcePKCSPBEOutputEncryptorBuilder。正确的代码(在MATLAB中,但转换为Java很简单)是:

java.security.Security.addProvider(org.bouncycastle.jce.provider.BouncyCastleProvider()); 
    keyGen = java.security.KeyPairGenerator.getInstance('RSA', 'BC'); 
    keyGen.initialize(2048, java.security.SecureRandom()); 
    keypair = keyGen.generateKeyPair(); 
    privateKey = keypair.getPrivate(); 
    builder=org.bouncycastle.pkcs.jcajce.JcaPKCS8EncryptedPrivateKeyInfoBuilder(privateKey); 

    m=org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers.pbeWithSHAAnd3_KeyTripleDES_CBC; 
    encryptorBuilder = org.bouncycastle.pkcs.jcajce.JcePKCSPBEOutputEncryptorBuilder(m); 
    password = 'test'; 
    outputBuilder = encryptorBuilder.build(password); 
    privKeyObj = builder.build(outputBuilder); 
    fos = java.io.FileOutputStream('testkey.pk8'); 
    fos.write(privKeyObj.getEncoded()); 
    fos.flush(); 
    fos.close(); 

这会生成DER格式的PCS#8文件。

openssl pkcs8 -inform DER -outform PEM -in testkey.pk8 -out testkey.pem 

现在返回PEM私钥。读取密钥:

myPath = java.nio.file.Paths.get(pwd,'testkey.pk8'); 
    encodedKey = java.nio.file.Files.readAllBytes(myPath); 
    privKeyObj =org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo(encodedKey); 
    cp=org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter(); 
    cp.setProvider('BC'); 

    decryptorBuilder = org.bouncycastle.pkcs.jcajce.JcePKCSPBEInputDecryptorProviderBuilder(); 
    inputBuilder = decryptorBuilder.build(password); 
    info = privKeyObj.decryptPrivateKeyInfo(inputBuilder); 
    decodedKey=cp.getPrivateKey(info); 

注意,在MATLAB,你并不需要声明返回的对象的类型,你不必把“新”在构造函数的前面。