PKCS#11 Smartcard getting error: javax.net.ssl.SSLHandshakeException due to java.security.InvalidKeyException: The RSA asymmetric cipher

PKCS#11 Smartcard getting error: javax.net.ssl.SSLHandshakeException due to java.security.InvalidKeyException: The RSA asymmetric cipher

情况

我正在做一个项目,我们必须让智能卡在 Linux 中工作。该卡由制造商 Izenpe 提供。每次与服务器进行 SSL 握手时,我都会收到 javax.net.ssl.SSLHandshakeException

我使用这些代码加载 Izenpe 驱动程序:

private final static String config_path3 = "name=IZENPE\nlibrary=/usr/lib/libbit4ipki.so";

...

String config = config_path3;
Provider provider = new SunPKCS11(new ByteArrayInputStream(config.getBytes()));
Security.removeProvider("IAIK");
Security.insertProviderAt(provider, 1);
try {
    keystore = KeyStore.getInstance("PKCS11", provider);
} catch (KeyStoreException e) {
    throw e;
}
KeyStore.Builder builder = KeyStore.Builder.newInstance("PKCS11", provider, 
        new KeyStore.CallbackHandlerProtection(new UtilTarjetas(). new callback()));
keystore = builder.getKeyStore();

它加载证书以在 table 中显示,我可以继续从服务器的响应中获取 OutputStream 的部分,当我们进行 SSL 握手(签名挑战)。完整堆栈跟踪如下:

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:1904)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:279)
    at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:1054)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:341)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:901)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:837)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1023)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1092)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
    at gestores.comunicacion.gisscide.HTTPS_TGSS.doHTTP_Get(HTTPS_TGSS.java:470)
    at gestores.comunicacion.Gestor_Comunicaciones$RecibeMensajesSSL.descargaMsgHTTPS(Gestor_Comunicaciones.java:1284)
    at gestores.comunicacion.Gestor_Comunicaciones$RecibeMensajesSSL.run(Gestor_Comunicaciones.java:1852)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.security.InvalidKeyException: The RSA asymmetric cipher only operates with RSA keys; unsupported key found (sun.security.pkcs11.P11Key$P11PrivateKey)
    at com.entrust.toolkit.security.provider.RSA.a(Unknown Source)
    at com.entrust.toolkit.security.provider.RSA.engineGetKeySize(Unknown Source)
    at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1052)
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1010)
    at javax.crypto.Cipher.init(Cipher.java:1209)
    at java.security.Signature$CipherAdapter.engineInitSign(Signature.java:1254)
    at java.security.Signature$Delegate.init(Signature.java:1128)
    at java.security.Signature$Delegate.chooseProvider(Signature.java:1085)
    at java.security.Signature$Delegate.engineInitSign(Signature.java:1158)
    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:1156)
    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:1049)
    ... 15 more

似乎在 SSL 握手中获取卡中的 unextractable 私钥以签署质询时失败,因为 PKCS#11 私钥不是 supported/recognized 有效。

通过将这一行添加到我的代码中,我得到了很多行关于 SSL 的日志。

Properties systemProps = System.getProperties();
systemProps.put("javax.net.debug", "all");          
System.setProperties(systemProps);

最后我可以看到这个:

SESSION KEYGEN:
PreMaster Secret:
0000: A5 F7 9C 89 A4 B5 B4 66   D4 DC CC 40 45 C8 41 07  .......f...@E.A.
0010: 0E F1 E9 5C 99 36 C8 84   06 B0 6B 95              ...\.6....k.
CONNECTION KEYGEN:
Client Nonce:
0000: 58 07 74 02 CD 8B 65 BB   E0 03 8D 53 95 C4 87 8C  X.t...e....S....
0010: EE 95 B2 92 C1 DF E8 CA   B0 7D E4 AD 16 B7 31 D2  ..............1.
Server Nonce:
0000: 4A 41 AA 83 DD 1D 9C DE   84 4A 56 40 A3 32 F7 53  JA.......JV@.2.S
0010: 18 48 32 BD 7A E2 3A 1D   19 AD 67 6E DD E1 3B 20  .H2.z.:...gn..; 
Master Secret:
0000: 72 58 C0 3D 90 67 2E 3B   B2 AE D4 54 15 AB 18 AA  rX.=.g.;...T....
0010: 95 73 91 9A DA AE EF 3D   77 A1 CD 7A 68 8B 37 56  .s.....=w..zh.7V
0020: 0F 05 64 EB DD 93 AF 6C   C4 C2 8A 75 A7 C2 CA 06  ..d....l...u....
Client MAC write Secret:
0000: 30 2C D3 A0 4C 2D 3F 67   ED B9 64 B8 3B 81 47 0E  0,..L-?g..d.;.G.
0010: D1 7B 75 A9                                        ..u.
Server MAC write Secret:
0000: 4B 22 25 8E 81 D1 55 6D   B9 40 0F 2A A2 26 49 F5  K"%...Um.@.*.&I.
0010: 66 6A 91 AE                                        fj..
Client write key:
0000: 72 BD C0 56 3C 1A E5 61   90 2C A6 AE AA FE B9 71  r..V<..a.,.....q
Server write key:
0000: C6 CE F4 C6 CE A4 E3 55   F6 2D 29 D6 2E 4C CA 7A  .......U.-)..L.z
Client write IV:
0000: 7D DB C8 17 F4 18 72 33   A1 DC 03 D6 2F 87 65 F1  ......r3..../.e.
Server write IV:
0000: 58 B1 4E BE 1A 90 0C B3   0D AE 5C 5B CD 36 74 4D  X.N.......\[.6tM
%% Invalidated:  [Session-3, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA]
Thread-7, SEND TLSv1 ALERT:  fatal, description = handshake_failure
Thread-7, WRITE: TLSv1 Alert, length = 2
[Raw write]: length = 7
0000: 15 03 01 00 02 02 28                               ......(
Thread-7, called closeSocket()
Thread-7, handling exception: javax.net.ssl.SSLHandshakeException: Error signing certificate verify
Finalizer, called close()
Finalizer, called closeInternal(true)

我不知道它是否相关,但在 www.ssllabs.com 中测试我的服务器站点时,我发现支持 TLSv1.2 但不支持 TLSv1.1。并且在日志中这里选择的算法没有在服务器的首选列表中列出:

那么,可能是什么原因呢?

我的想法:


虽然我不太精通 PKCS#11(当我想到它时也不精通 SSL),但根据您的描述和日志文件,以下项目引起了我的注意并让我思考:

考虑到上面抛出的 InvalidKeyException 和突出显示的算法(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA),我倾向于认为密钥是椭圆曲线密钥,而不是 RSA(在屏幕截图中,它声明安全性由TLS_ECDHE 等于使用 2048 位的 RSA 得到的)。 因此,在此过程中的某个地方,以编程方式或格式错误的证书选择了错误的签名提供程序(RSA 而不是 ECDSA)。

希望对您有所帮助。

看起来像 Java JCE 的 SSL 连接,正在使用 Entrust Provider。

如果您查看堆栈跟踪:

Caused by: java.security.InvalidKeyException: The RSA asymmetric cipher only operates with RSA keys; unsupported key found (sun.security.pkcs11.P11Key$P11PrivateKey) at com.entrust.toolkit.security.provider.RSA.a(Unknown Source) at com.entrust.toolkit.security.provider.RSA.engineGetKeySize(Unknown Source) at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1052)

此错误是由 Entrust JCE 提供程序引发的。它可能只需要 Java 的 RSA 密钥,但正在向它发送一个它可能无法处理的 PKCS11 密钥。

因此,请尝试同时删除 'Entrust' 提供程序。

如果这不起作用,请尝试将 SunPKCS11 provider 实例传递给 SSLContext,无论您在哪里使用它来启动安全连接。