5

ONE ECキーペアによって生成されたキーを使用してAES-256 / GCMでファイルを暗号化するプログラムを(JavaでBouncy Castle APIを使用して)書いています。対称暗号化部分は完全に機能していますが、鍵の生成が困難であることがわかりました。javax.crypto.KeyAgreement.init() メソッドで ECPublicKey オブジェクトを使用しようとすると、次のエラーが返されます。

Exception in thread "main" java.security.InvalidKeyException: ECDH key agreement requires ECPrivateKey for initialisation
    at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyAgreementSpi.initFromKey(Unknown Source)
    at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyAgreementSpi.engineInit(Unknown Source)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:461)
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:435)
    at Encrpytion.generateKey(Encrpytion.java:188)  ---aKA.init(key);---
    at Encrpytion.main(Encrpytion.java:40) ---byte[] key = generateKey();---

メソッドのソース コードは次のとおりです。

public static byte[] generateKey() {
    KeyStore ks = KeyStore.getInstance("PKCS12");
    FileInputStream fis = new FileInputStream("file.pfx");
    Scanner input = new Scanner(System.in);
    char[] chars = {};
    System.out.println("Enter the password for your .pfx: ");
    chars = input.nextLine().toCharArray();
    input.close();
    Enumeration aliasEnum = null;
    ks.load(fis, chars);
    aliasEnum = ks.aliases();
    Key key = null;
    Certificate cert = null;
    while (aliasEnum.hasMoreElements()){
        String param = (String)aliasEnum.nextElement();
        if (ks.isKeyEntry(param))  {
            String keyName = param;
            key = ks.getKey(keyName,chars);
        }
        cert = ks.getCertificateChain(param)[0];
    }
    KeyPair kp = new KeyPair(cert.getPublicKey(),(ECPrivateKey) key);
    KeyAgreement aKA = null;
    aKA = KeyAgreement.getInstance("ECDH", "BC");
    aKA.init(key);
    aKA.doPhase(kp.getPublic(), true);
    return aKA.generateSecret();
}

証明書の PrivateKey にアクセスするにはどうすればよいですか?

**更新: **更新されたソースコード

** 編集 ** 次のコマンドと手順を使用して、問題を実証するためのテスト ファイルを作成できます。

#Make root key
openssl ecparam -name secp521r1 -genkey -out root.key
#password protect key
openssl ec -in root.key -out root.key -aes256
####change req x509_attributes to rootCA
#selfsign root
openssl req -new -x509 -key root.key -out root.crt -days 1825 -config openssl.cfg
###comment out req x509_attributes
#make new key for clientCA
openssl ecparam -name secp521r1 -genkey -out client.key
#make clientCA csr
openssl req -new -sha384 -key client.key -out client.csr -config openssl.cfg
#sign clientCA
openssl ca -out client.crt -name root -in client.csr -config openssl.cfg
#make client key
openssl ecparam -name secp521r1 -genkey -out client.key
#make server csr
openssl req -new -sha384 -key client.key -out client.csr -config openssl.cfg
#sign server cert
openssl ca -out client.crt -name client -in client.csr -config openssl.cfg
#MAKE CHAIN - copy base64 encoded root and intermidiate client ca into same "chain.cer" #export user cert 
openssl pkcs12 -export -chain -CAfile chain.crt -in client.crt -inkey client.key -out client.pfx -aes256
4

1 に答える 1

3

任意のエイリアスについて、との1つだけkeycertnull以外になります。この場合、明らかcertにnullではなく、キーはnullでした。キーストアにEC秘密鍵がある場合は、それを見つけるためにもう少し努力する必要があります。およびを使用してテストすることにより、エイリアスにあるエントリの種類を判別できます。isCertificateEntryisKeyEntry

編集1

エラーメッセージは、実際にはbouncycastleライブラリからのものであるため、残念ながら混乱を招きます。で参照されているクラスはでECDH key agreement requires ECPrivateKeyなく java.security.interfaces.ECPrivateKeyorg.bouncycastle.jce.interfaces.ECPrivateKey

OPサンプルコードの次の短い適応は、これを克服する1つの方法を示しています。

import org.bouncycastle.jce.provider.JCEECPrivateKey;
import org.bouncycastle.jce.provider.JCEECPublicKey;
// ...
// . <original example code goes here>
// .
JCEECPrivateKey ecPrivKey = new JCEECPrivateKey((ECPrivateKey) key);
JCEECPublicKey ecPubKey = new JCEECPublicKey((ECPublicKey) cert.getPublicKey());
KeyPair kp = new KeyPair(ecPubKey, ecPrivKey);
KeyAgreement aKA = null;
aKA = KeyAgreement.getInstance("ECDH", "BC");
aKA.init(ecPrivKey);
aKA.doPhase(kp.getPublic(), true);
return aKA.generateSecret();
// ...
于 2012-12-14T00:59:03.150 に答える