SSLHandshakeException after deleting SHA1 cert: Received fatal alert: bad_certificate. Server log: SEC_ERROR_REUSED_ISSUER_AND_SERIAL

时间:2017-08-04 12:48:41

标签: java ssl sha1 sslhandshakeexception

Our Java Swing + Visual Basic APP let users authenticate against server with SSL connection. Now two user in the same entity client sharing a smart card suddenly encounter a problem: they cannot connect to the server with Java part, but with VB modules it is normal.

At server side we formerly had both ancert SHA1 and SHA256 root. It was when server admins deleted ANCERT SHA1 root and sub-root certs, we began to have the problem of "bad_certificate".

After we added -Djavax.net.debug=all, at last of the generated log we see the error happens after CertificateVerify and Client Finish:

...
*** CertificateVerify
[write] MD5 and SHA1 hashes:  len = 262
0000: 0F 00 01 02 01 00 0C F5   8A 0A 9C 38 E9 6B E4 B6  ...........8.k..
0010: AC 2D 35 26 61 E3 56 72   66 DE B9 E0 AE CD B2 7B  .-5&a.Vrf.......
0020: 41 AF EB 66 9B 48 05 11   94 75 0D 0F 01 4B CA E6  A..f.H...u...K..
0030: 64 60 B7 5D 85 5D 61 1B   EA 7F 38 F1 5D D4 91 AE  d`.].]a...8.]...
0040: 04 84 19 3A 76 75 1E 87   4D C7 42 AB 16 9E 07 AD  ...:vu..M.B.....
0050: 7D 60 9A A2 A8 94 B9 2F   08 79 40 AA 96 14 2E F4  .`...../.y@.....
0060: 88 CA 72 00 46 8F EF D5   A2 6D 6B 7C B9 99 44 52  ..r.F....mk...DR
0070: FB CA F8 F8 00 D1 95 5E   15 B9 AD C6 1B 51 71 FB  .......^.....Qq.
0080: 6E 34 17 EC 0D D0 1B 8E   49 D7 DF F0 96 82 E6 27  n4......I......'
0090: F7 1B 2B 39 42 D5 CE 92   30 27 E5 07 7D 6C 87 6F  ..+9B...0'...l.o
00A0: CE CD 81 DD 8A 04 D6 F2   EE 36 D4 2D FC 3B 00 58  .........6.-.;.X
00B0: 93 D5 85 D9 EB C4 DC 30   FC 91 E5 CB 44 8B 6A A2  .......0....D.j.
00C0: 38 96 DD 21 B0 C5 C3 27   34 FC 55 97 00 26 5F 17  8..!...'4.U..&_.
00D0: F3 53 05 45 23 81 00 C2   36 FC C1 0B B7 45 8B 87  .S.E#...6....E..
00E0: 61 F1 21 65 AA F6 34 B4   15 85 AF A5 B2 21 C3 65  a.!e..4......!.e
00F0: 7E 9D B1 F3 F8 13 8D 58   14 1A F1 CE 9A 7F 53 6C  .......X......Sl
0100: 6F 96 A3 77 8F 9F                                  o..w..
Thread-7, WRITE: TLSv1.1 Handshake, length = 262
[Raw write]: length = 267
0000: 16 03 02 01 06 0F 00 01   02 01 00 0C F5 8A 0A 9C  ................
0010: 38 E9 6B E4 B6 AC 2D 35   26 61 E3 56 72 66 DE B9  8.k...-5&a.Vrf..
0020: E0 AE CD B2 7B 41 AF EB   66 9B 48 05 11 94 75 0D  .....A..f.H...u.
0030: 0F 01 4B CA E6 64 60 B7   5D 85 5D 61 1B EA 7F 38  ..K..d`.].]a...8
0040: F1 5D D4 91 AE 04 84 19   3A 76 75 1E 87 4D C7 42  .]......:vu..M.B
0050: AB 16 9E 07 AD 7D 60 9A   A2 A8 94 B9 2F 08 79 40  ......`...../.y@
0060: AA 96 14 2E F4 88 CA 72   00 46 8F EF D5 A2 6D 6B  .......r.F....mk
0070: 7C B9 99 44 52 FB CA F8   F8 00 D1 95 5E 15 B9 AD  ...DR.......^...
0080: C6 1B 51 71 FB 6E 34 17   EC 0D D0 1B 8E 49 D7 DF  ..Qq.n4......I..
0090: F0 96 82 E6 27 F7 1B 2B   39 42 D5 CE 92 30 27 E5  ....'..+9B...0'.
00A0: 07 7D 6C 87 6F CE CD 81   DD 8A 04 D6 F2 EE 36 D4  ..l.o.........6.
00B0: 2D FC 3B 00 58 93 D5 85   D9 EB C4 DC 30 FC 91 E5  -.;.X.......0...
00C0: CB 44 8B 6A A2 38 96 DD   21 B0 C5 C3 27 34 FC 55  .D.j.8..!...'4.U
00D0: 97 00 26 5F 17 F3 53 05   45 23 81 00 C2 36 FC C1  ..&_..S.E#...6..
00E0: 0B B7 45 8B 87 61 F1 21   65 AA F6 34 B4 15 85 AF  ..E..a.!e..4....
00F0: A5 B2 21 C3 65 7E 9D B1   F3 F8 13 8D 58 14 1A F1  ..!.e.......X...
0100: CE 9A 7F 53 6C 6F 96 A3   77 8F 9F                 ...Slo..w..
Thread-7, WRITE: TLSv1.1 Change Cipher Spec, length = 1
[Raw write]: length = 6
0000: 14 03 02 00 01 01                                  ......
*** Finished
verify_data:  { 54, 35, 53, 118, 12, 242, 190, 4, 226, 234, 192, 46 }
***
[write] MD5 and SHA1 hashes:  len = 16
0000: 14 00 00 0C 36 23 35 76   0C F2 BE 04 E2 EA C0 2E  ....6#5v........
Padded plaintext before ENCRYPTION:  len = 64
0000: A9 E5 26 50 4D 1D BE 8B   92 2E 77 12 24 0E DB C5  ..&PM.....w.$...
0010: 14 00 00 0C 36 23 35 76   0C F2 BE 04 E2 EA C0 2E  ....6#5v........
0020: A5 44 16 F6 70 AC 7F 9A   40 CD 5B 4C B9 CD 88 7D  .D..p...@.[L....
0030: 42 78 85 30 0B 0B 0B 0B   0B 0B 0B 0B 0B 0B 0B 0B  Bx.0............
Thread-7, WRITE: TLSv1.1 Handshake, length = 64
[Raw write]: length = 69
0000: 16 03 02 00 40 0C A2 DA   FC 1A 9E CE B0 D6 2F 7B  ....@........./.
0010: 23 9E A9 00 D3 3B FC 2A   C7 DD 5D 22 A6 36 B3 E1  #....;.*..]".6..
0020: CE EB FD 48 C7 55 D3 5B   AF FC 37 3E 49 86 9A 6F  ...H.U.[..7>I..o
0030: 79 A5 FD 5B 60 06 F4 A9   89 CD F4 26 D9 FE F3 9B  y..[`......&....
0040: 78 E0 65 2D 56                                     x.e-V
[Raw read]: length = 5
0000: 15 03 02 00 02                                     .....
[Raw read]: length = 2
0000: 02 2A                                              .*
Thread-7, READ: TLSv1.1 Alert, length = 2
Thread-7, RECV TLSv1.1 ALERT:  fatal, bad_certificate
%% Invalidated:  [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
Thread-7, called closeSocket()
Thread-7, handling exception: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate

At server side, when the client connects, this error occurs:

[07/Jul/2017:13:33:18] failure (3354): HTTP3068: Error receiving request from 37.222.168.137 (SEC_ERROR_REUSED_ISSUER_AND_SERIAL: Attempting to import a cert which conflicts with issuer/serial of existing cert.)

We have no clue why it stops working.

  • VB modules also connect to the same server, same URL and it works. I don't have VB codes. So I guess the card is good.
  • The trust store file in the application has included the issuer ANCERT Certificados para empleados V2(sub-root), as well as the root ANCERT CGN V2 (root).

Why it is happening?

EDIT:

In the local trust store we have these certs:

ancert root cert (sha1)
        |
        - ancert sub-root cert (sha1) 

And how the chain was built before the problem:

ancert root cert (sha1)
        |
        - ancert sub-root cert (sha1) 
                    |
                    - user cert (sha256)

At server side, the SHA1 root cert has the same serial number as the SHA256 root cert.

So I thought it was because when building the chain, Java looks into the chain in the user cert, and wants to find a chain in server as indicated in this chain, so it expects intermediate SHA1 and root SHA256, but now when all SHA1 cert are deleted, it can only find SHA256 with same serial number, so that could be the cause, but I was wrong.

Because now we have another user with this chain as shown in his cert's public part:

ancert root cert (sha256)
        |
        - ancert sub-root cert (sha256) 
                    |
                    - user cert (sha256)

If my theory stands, this user will not complain because SHA256 certs are always present at server side, but now he complains too.

So what is the reason?

1 个答案:

答案 0 :(得分:1)

我找到了答案:事实证明,在IE信任库中删除SHA1根CA证书后,它与服务器端SHA256的序列号相同,所有都开始重新运行。中间CA证书的序列号不会重复。

我相信我以前的猜测是部分的:在进行身份验证时,在构建用户证书链时,而不是尝试构建链,因为用户证书指示,Java似乎查找中间和root来自Windows系统证书存储区的证书,即我们可以在certmgr中看到的“可信中间/根CA”部分。而且,不幸的是,在安装用户证书时,安装程​​序会将SHA1和SHA256根证书添加到此商店中。

并且,Java似乎假设在这个商店中一切都井井有条,并且不会像序列号那样重复;在看到SHA256根证书之前它会看到SHA1证书。因此,它用它构建链,并将其发送到服务器;但是在服务器端,它看到SHA2具有相同的序列号,因此存在冲突。

至于VB方面,我想这是因为MS以另一种方式构建了证书链(并考虑到另一种意识形态:假设发现的第一个链不一定是最好的,有时,它很容易失败),试图建立所有可能的链,最后,选择正确的链。根据{{​​3}}:

  

如果我们谈论Microsoft实现(只是我熟悉的一个例子),他们的CCE会构建一个或多个链(尽可能多)而不执行立即验证。他们只需获取证书并尝试执行基本规则,将每个证书绑定在链中的正确位置。构建所有链时,每个链都根据RFC5280中描述的规则进行验证。经过验证,可能存在多个可信和有效链的情况。 CCE使用自己的选择逻辑从链的集合中仅选择一个链。

因此,VB代码不受这种错误/重复的影响,而Java此时更容易受到攻击。

此问题的修订:

我想序列号的重复是注意力,迫使用户更新证书,而不会意识到可能造成的混淆;

并且,服务器管理员应该提前通知我们这个更改;我们在用户报告后一周收到了这些信息。

最后,这是主动反应式编程之间长期争议的另一个证据。我认为Java偏爱前者,因为我在一个证书库中遇到了与不同证书的重复别名相关的另一个问题,在那里我看到了Java读取证书的方式(通过迭代所有别名并获取它看到的第一个,哪个与此相似)强烈建议 Java人员认为证书库中不应存在重复的别名。这是一个已知的错误,描述为this answer。但是,我认为这完全取决于您的目标是谁,有经验的网络管理员或普通用户。