2016-03-02 42 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,你並不需要聲明返回的對象的類型,你不必把「新」在構造函數的前面。