7

次のコードは、PKCS#11 デバイス (スマート カード) を使用してクライアント認証 SSL コンテキストを作成します。それはすべて Java 6 で問題なく動作します。

// Configure the SunPkcs11 provider
String pkcs11config;
pkcs11config = "name = Cryptoki";
pkcs11config += "\nlibrary = /SCDriver/libbit4ipki.dylib";
InputStream confStream = new ByteArrayInputStream(pkcs11config.getBytes());
SunPKCS11 sunpkcs11 = new SunPKCS11(confStream);
Security.addProvider(sunpkcs11);

// Specify keystore builder parameters for PKCS#11 keystores
Builder scBuilder = Builder.newInstance("PKCS11", sunpkcs11, new KeyStore.CallbackHandlerProtection(new PasswordRetriever()));

// Create and init KeyManagerFactory
KeyManagerFactory factory = KeyManagerFactory.getInstance("NewSunX509");
factory.init(new KeyStoreBuilderParameters(scBuilder));

// create and init ssl context
m_ssl_context = SSLContext.getInstance("TLS");
m_ssl_context.init(factory.getKeyManagers(), new TrustManager[] {new PkTrustManager()}, null);      
SSLContext.setDefault(m_ssl_context);

PkTrustManagerは単純で「空の」クラスであり、サーバー/クライアント証明書を有効に使用し、PasswordRetrieverダイアログ ボックスを介してパスワードを要求するだけです (要求に応じて、これらのソース コードを投稿します)。代わりに Java 7 では、ssl コンテキストの SSL ハンドシェイク中に次の例外が発生します。

java.security.InvalidKeyException: Class does not represent an RSA key: sun.security.pkcs11.P11Key$P11PrivateKey
    at iaik.pkcs.pkcs1.RSACipher.engineInit(Unknown Source)
    at iaik.pkcs.pkcs1.RSACipher.engineInit(Unknown Source)
    at iaik.security.rsa.RSA.init(Unknown Source)
    at iaik.security.rsa.RawRSASignature.engineInitSign(Unknown Source)
    at java.security.SignatureSpi.engineInitSign(SignatureSpi.java:103)
    at java.security.Signature.initSign(Signature.java:529)
    at sun.security.ssl.RSASignature.engineInitSign(RSASignature.java:125)
    at java.security.Signature$Delegate.engineInitSign(Signature.java:1136)
    at java.security.Signature.initSign(Signature.java:529)
    at sun.security.ssl.HandshakeMessage$CertificateVerify.<init>(HandshakeMessage.java:1556)
    at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:982)
    ... 14 more

最良の場合、Java の内部で何かが変更されたと言えますが、Oracle のドキュメントを確認したところ、NewSunX509 キー マネージャーやその他のコンポーネントに想定される変更は見つかりませんでした。コードを再確認したところ、仕様に準拠しているように見えます (確かに何か見落としがあります!)。

構成フラグを追加しようとしました:

System.setProperty("javax.net.ssl.keyStoreType", "pkcs11");
System.setProperty("javax.net.ssl.keyStore", "NONE");
System.setProperty("javax.net.ssl.trustStoreType", "pkcs11");
System.setProperty("javax.net.ssl.trustStore", "NONE");
System.setProperty("javax.net.ssl.keyStoreProvider", sunpkcs11.getName() );
JCEMapper.setProviderId(sunpkcs11.getName());

しかし、変更はありません、同じエラー...そして、すべてが機能するJava 6では必要ありません。誰でも助けてくれるか、何かアイデアがあれば、事前に感謝します!

PS: @owlstead からのリクエストにより-Djava.security.debug=sunpkcs11が追加され、次の出力が得られました。

SunPKCS11 loading ---DummyConfig-1---
sunpkcs11: Initializing PKCS#11 library /SCDriver/libbit4ipki.dylib
Information for provider SunPKCS11-Cryptoki
Library info:
  cryptokiVersion: 2.20
  manufacturerID: bit4id srl                      
  flags: 0
  libraryDescription: bit4id PKCS#11                  
  libraryVersion: 1.02
All slots: 0
Slots with tokens: 0
Slot info for slot 0:
  slotDescription: bit4id miniLector-U38 00 00                                     
  manufacturerID: unknown                         
  flags: CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE | CKF_HW_SLOT
  hardwareVersion: 0.00
  firmwareVersion: 0.00
Token info for token in slot 0:
  label: CNS                             
  manufacturerID: ST Incard                       
  model: CNS (LB)        
  serialNumber: 7420057800291590
  flags: CKF_RNG | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED
  ulMaxSessionCount: CK_EFFECTIVELY_INFINITE
  ulSessionCount: 0
  ulMaxRwSessionCount: CK_EFFECTIVELY_INFINITE
  ulRwSessionCount: CK_UNAVAILABLE_INFORMATION
  ulMaxPinLen: 8
  ulMinPinLen: 5
  ulTotalPublicMemory: 31988
  ulFreePublicMemory: CK_UNAVAILABLE_INFORMATION
  ulTotalPrivateMemory: 780
  ulFreePrivateMemory: CK_UNAVAILABLE_INFORMATION
  hardwareVersion: 0.00
  firmwareVersion: 0.00
  utcTime: 0000000000000000
Mechanism CKM_RSA_PKCS:
  ulMinKeySize: 1024
  ulMaxKeySize: 1024
  flags: 2561 = CKF_HW | CKF_DECRYPT | CKF_SIGN
Mechanism CKM_RSA_PKCS_KEY_PAIR_GEN:
  ulMinKeySize: 1024
  ulMaxKeySize: 1024
  flags: 65537 = CKF_HW | CKF_GENERATE_KEY_PAIR
Mechanism CKM_SHA1_RSA_PKCS:
  ulMinKeySize: 1024
  ulMaxKeySize: 1024
  flags: 2049 = CKF_HW | CKF_SIGN
Mechanism CKM_SHA_1:
  ulMinKeySize: 0
  ulMaxKeySize: 0
  flags: 1024 = CKF_DIGEST
Mechanism CKM_SHA256:
  ulMinKeySize: 0
  ulMaxKeySize: 0
  flags: 1024 = CKF_DIGEST
Mechanism CKM_SHA256_RSA_PKCS:
  ulMinKeySize: 1024
  ulMaxKeySize: 1024
  flags: 2049 = CKF_HW | CKF_SIGN
Mechanism CKM_SHA384:
  ulMinKeySize: 0
  ulMaxKeySize: 0
  flags: 1024 = CKF_DIGEST
Mechanism CKM_SHA384_RSA_PKCS:
  ulMinKeySize: 1024
  ulMaxKeySize: 1024
  flags: 2049 = CKF_HW | CKF_SIGN
Mechanism CKM_SHA512:
  ulMinKeySize: 0
  ulMaxKeySize: 0
  flags: 1024 = CKF_DIGEST
Mechanism CKM_SHA512_RSA_PKCS:
  ulMinKeySize: 1024
  ulMaxKeySize: 1024
  flags: 2049 = CKF_HW | CKF_SIGN
Mechanism CKM_RSA_X_509:
  ulMinKeySize: 1024
  ulMaxKeySize: 1024
  flags: 2561 = CKF_HW | CKF_DECRYPT | CKF_SIGN
Password per token PKCS11 [SunPKCS11-Cryptoki]: sunpkcs11: login succeeded
sunpkcs11: user already logged in
javax.net.ssl.SSLHandshakeException: Error signing certificate verify
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1886)
    *....... (continues with the exception as described above)*

注: Java 6 の最後の更新で、私のコードは Java 6 でも動作しなくなりました :(

4

1 に答える 1

8

次のコード行を追加することで解決しました。

Security.removeProvider("IAIK");

行の前に:

Security.addProvider(sunpkcs11);

これは、java6 と java7 のすべてのバージョンで正しく動作します (java8 で再び何かを台無しにしないことを願っています... :)

IAIK プロバイダーは、自身を PKCS11 プロバイダーとして挿入しているように見えますが、それをソフトウェア キーとして使用して秘密キーを呼び出しています。これは実際にはソフトウェア プロバイダーであるためです。

于 2013-03-29T13:02:47.303 に答える