it-swarm-tr.com

Java'da OpenSSL tarafından üretilen anahtarlar nasıl kullanılır?

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
11
BRabbit27

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).

  • Anahtar deposu kullanım açısından:

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).

10
Bruno