Genel ve Özel anahtarlarım ve sertifikam var. OpenSSL'de yaratılanlar (neden? Çünkü bunu OpenSSL'de yapmam istendi). Şimdi bunları dijital imzalar kullanan bir Java uygulaması) yapmak için kullanmak istiyorum. Bilgileri şifrelemek/şifresini çözmek için özel ve genel anahtarlarımı nasıl kullanabilirim (ve verilerin Java içindeki bunu yapmama izin veren sınıflar nelerdir?)
Anahtarlarım düz metin gibi bir şey vardır:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDuyg3h0VbP9iZ6RCxSU6x4WX4
anAwedMVUTqF0WHlvHl1Kiqa6N6TiUk23uXAVUX8RwLFjXWHlG0xwW7mGByA2mX9
5oPQpQFu8C70aMuUotGv87iiLi0UKCZV+9wS9rMdg5LHu1mMPilwgOO6MlyTxKem
-----END PUBLIC KEY-----
GÜNCELLEME
Bu kodu yaptım ama hala bir dize imzalamak için özel anahtarı kullanamazsınız.
public void encryptHash(String hashToEncrypt, String pathOfKey, String Algorithm) {
FileInputStream fis = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len;
File f = new File(pathOfKey);
fis = new FileInputStream(pathOfKey);
len = 0;
while((len = fis.read()) != -1){
baos.write(len);
}
KeyFactory kf = KeyFactory.getInstance(Algorithm); //Algorithm = "RSA"
KeySpec keySpec = new PKCS8EncodedKeySpec(baos.toByteArray());
baos.close();
PrivateKey privateKey = kf.generatePrivate(keySpec); //Here's the exception thrown
Signature rsaSigner = Signature.getInstance("SHA1withRSA");
rsaSigner.initSign(privateKey);
fis = new FileInputStream(hashToEncrypt);
BufferedInputStream bis = new BufferedInputStream(fis);
byte[] buffer = new byte[1024];
len = 0;
while((len = bis.read(buffer)) >= 0){
try {
rsaSigner.update(buffer, 0, len);
} catch (SignatureException ex) {
Logger.getLogger(DataEncryptor.class.getName()).log(Level.SEVERE, null, ex);
}
}
bis.close();
byte[] signature = rsaSigner.sign();
System.out.println(new String(signature));
}
elde ettiğim istisna
dic 09, 2011 12:49:02 PM firmaelectronica.DataEncryptor encryptHash
Grave: null
Java.security.spec.InvalidKeySpecException: Java.security.InvalidKeyException: IOException : DER input, Integer tag error
at Sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.Java:217)
at Java.security.KeyFactory.generatePrivate(KeyFactory.Java:372)
at firmaelectronica.DataEncryptor.encryptHash(DataEncryptor.Java:40)
at firmaelectronica.FirmaElectronica.main(FirmaElectronica.Java:39)
Caused by: Java.security.InvalidKeyException: IOException : DER input, Integer tag error
at Sun.security.pkcs.PKCS8Key.decode(PKCS8Key.Java:361)
at Sun.security.pkcs.PKCS8Key.decode(PKCS8Key.Java:367)
at Sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.Java:91)
at Sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.Java:75)
at Sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.Java:316)
at Sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.Java:213)
... 3 more
Bu formda ortak bir anahtarınız varsa (ve bir sertifika içinde değil), BouncyCastle 's PEMReader
kullanmanızı öneririm. readObject()
yöntemi biçimler için çok şey okuyabilir: genel anahtarlar, sertifikalar, özel anahtarlar (yöntemi bir parola ile kullanmanız gerekebilir) ...
BouncyCastle'ı kullanmak istemiyorsanız, sertifikaları CertificateFactory kullanarak okuyabilirsiniz (örneklere bakın). InputStream'de PEM biçiminde bir sertifika ile:
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(inputStream);
Özel anahtarlar için, özel anahtarınız DER biçiminde bir PKCS # 8 yapısı ise, PKCS8EncodedKeySpec öğesini kullanarak doğrudan okuyabilirsiniz. Örneğin:
KeyFactory kf = KeyFactory.getInstance("RSA");
// Read privateKeyDerByteArray from DER file.
KeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyDerByteArray);
PrivateKey key = kf.generatePrivate(keySpec);
Özel anahtarınızı openssl pkcs8 -topk8
Kullanarak PKCS # 8'e dönüştürebilirsiniz (-outform DER
'U unutmayın, her ikisi de Java ve OpenSSL).
Anahtarları işlemek için fazla programlama yapmak istemiyorsanız, Java ve OpenSSL) arasında geçiş yapmak için PKCS # 12 biçimini kullanmak uygun olur.
OpenSSL ile ürettiğiniz anahtarlar ve sertifikalar zaten bir p12 kabında değilse:
openssl pkcs12 -export -in cert.pem -inkey key.pem -out store.p12
Genel olarak, doğrudan Java'nın "PKCS12
" Anahtar deposu türünü (varsayılan olarak "JKS
" yerine) kullanabilirsiniz.
Gerekirse, bu PKCS12 anahtar deposunu keytool
(Java 6+) kullanarak başka bir formata (örneğin JKS) dönüştürebilirsiniz:
keytool -importkeystore -srckeystore store.p12 -srcstoretype PKCS12 \
-destkeystore store.jks -deststoretype JKS
(Aslında, bu sor .
Her iki durumda da, PEMReader
kullanarak veya anahtarınızı/sertifikanızı KeyStore
öğesinden yükleyerek, PrivateKey
ve Certificate
(veya PublicKey
doğrudan).
Bir Certificate
imzasının, belirli bir ortak anahtarla eşleşen özel anahtar ile verify(PublicKey)
yöntemini kullanarak yapıldığını doğrulayabilirsiniz.
Bunlarla birlikte dijital imza API'sı da kullanabilirsiniz. Herhangi bir belge imzası için daha genel bir API ve onunla birlikte bir sertifika imzasını doğrulamak istemem (ayrıca zinciri oluşturacağı için bunun için sertifika yolu API'sını kullanmayı tercih ederim).