novitski / bitcoinj

Automatically exported from code.google.com/p/bitcoinj
Apache License 2.0
0 stars 0 forks source link

Bitpay: Version 1 certificates can't be used as CA ones #521

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
When trying out BIP70+72 support from the Bitpay site, I get the following 
exception:

(sorry about the formatting, logging for background threads somehow is broken 
with my current slf4j+android setup)

I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat[backgroundThread] got invalid 
payment request
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: 
java.security.cert.CertPatcom.google.bitcoin.protocols.payments.PaymentRequestEx
ception$PkiVerificationException: 
java.security.cert.CertPathValidatorException: Trust anchor for certification 
path not found.
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat at 
com.google.bitcoin.protocols.payments.PaymentSession.verifyPki(PaymentSession.ja
va:488) ~[na:0.0]
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat at 
com.google.bitcoin.protocols.payments.PaymentSession.<init>(PaymentSession.java:
209) ~[na:0.0]
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat at 
de.schildbach.wallet.ui.InputParser.parseAndHandlePaymentRequest(InputParser.jav
a:351) ~[na:0.0]
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat at 
de.schildbach.wallet.ui.InputParser$StreamInputParser.parse(InputParser.java:267
) ~[na:0.0]
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat at 
de.schildbach.wallet.ui.RequestPaymentRequestTask$HttpRequestTask$1.run(RequestP
aymentRequestTask.java:104) ~[na:0.0]
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat at 
android.os.Handler.handleCallback(Handler.java:730) ~[na:0.0]
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat at 
android.os.Handler.dispatchMessage(Handler.java:92) ~[na:0.0]
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat at 
android.os.Looper.loop(Looper.java:137) ~[na:0.0]
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat at 
android.os.HandlerThread.run(HandlerThread.java:61) ~[na:0.0]
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPatCaused by: 
java.security.cert.CertPathValidatorException: Trust anchor for certification 
path not found.
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat at 
com.android.org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidat
e(PKIXCertPathValidatorSpi.java:127) ~[na:0.0]
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat at 
java.security.cert.CertPathValidator.validate(CertPathValidator.java:190) 
~[na:0.0]
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat at 
com.google.bitcoin.protocols.payments.PaymentSession.verifyPki(PaymentSession.ja
va:435) ~[na:0.0]
I/InputParsercom.google.bitcoin.protocols.payments.PaymentRequestException$PkiVe
rificationException: java.security.cert.CertPat ... 8 common frames omitted

The request is being fetched from https://bitpay.com/i/X5h6Q9tD6v4i5gj8JX6en9

I tried to print their chain, but somehow I don't see a root CA at all.

I/InputParser(15640): [backgroundThread] Certificate:
I/InputParser(15640):     Data:
I/InputParser(15640):         Version: 3 (0x2)
I/InputParser(15640):         Serial Number:
I/InputParser(15640):             4e:e6:f1:7f:73:8e:d9
I/InputParser(15640):     Signature Algorithm: sha1WithRSAEncryption
I/InputParser(15640):         Issuer: C=US
I/InputParser(15640):         Validity
I/InputParser(15640):             Not Before: May 14 22:21:38 2012 GMT
I/InputParser(15640):             Not After : May 14 22:21:38 2014 GMT
I/InputParser(15640):         Subject: 
1.3.6.1.4.1.311.60.2.1.3=US/1.3.6.1.4.1.311.60.2.1.2=Florida/businessCategory=Pr
ivate Organization/serialNumber=L11000063599
I/InputParser(15640):         Subject Public Key Info:
I/InputParser(15640):             Public Key Algorithm: rsaEncryption
I/InputParser(15640):                 Public-Key: (2048 bit)
I/InputParser(15640):                 Modulus:
I/InputParser(15640):                     
00:ed:25:bf:d7:b9:4e:06:e0:c2:99:fd:10:1e:62:
I/InputParser(15640):                     
16:5d:ab:2e:f1:fc:a1:1f:20:cc:a4:53:42:82:ef:
I/InputParser(15640):                     
54:49:89:17:90:a4:6c:0e:48:40:f9:1e:88:9b:53:
I/InputParser(15640):                     
ea:7b:49:7b:56:82:d6:b3:8d:e2:1f:b9:f2:8b:c1:
I/InputParser(15640):                     
23:cf:a0:23:60:51:5b:ee:5f:6f:83:26:b2:f8:13:
I/InputParser(15640):                     
20:b1:cc:2c:22:95:34:12:67:a8:34:af:9c:c1:cc:
I/InputParser(15640):                     
7a:97:85:4c:1a:8d:ba:b7:2d:93:29:8b:3c:08:86:
I/InputParser(15640):                     
07:71:44:6d:e6:37:ab:64:8f:99:05:b9:26:a8:bb:
I/InputParser(15640):                     
55:2a:35:7a:16:7b:a5:d5:66:90:b6:28:2f:d4:6c:
I/InputParser(15640):                     
7b:69:86:d5:e2:1b:b5:2e:00:64:a7:19:5a:fb:53:
I/InputParser(15640):                     
97:d0:db:6c:7c:ee:be:24:76:2c:db:ee:4d:5b:bc:
I/InputParser(15640):                     
57:cf:d3:7b:85:9d:a4:93:33:f8:aa:62:2f:4f:6a:
I/InputParser(15640):                     
6f:43:79:4c:64:7d:e3:d1:74:cc:e3:34:2b:2a:4c:
I/InputParser(15640):                     
0b:c6:e6:14:e8:1b:36:e6:69:82:17:bb:d0:40:8b:
I/InputParser(15640):                     
09:b6:ab:fa:d2:6c:ad:bb:f3:ff:dc:98:64:0f:e1:
I/InputParser(15640):                     
70:7d:1d:9f:ce:eb:1c:3e:55:12:c3:a4:7b:da:79:
I/InputParser(15640):                     
02:ec:51:d5:75:d6:86:bc:f1:2f:d4:0f:32:e4:0b:
I/InputParser(15640):                     bb:f3
I/InputParser(15640):                 Exponent: 65537 (0x10001)
I/InputParser(15640):         X509v3 extensions:
I/InputParser(15640):             X509v3 Basic Constraints: critical
I/InputParser(15640):                 CA:FALSE
I/InputParser(15640):             X509v3 Extended Key Usage: 
I/InputParser(15640):                 TLS Web Server Authentication, TLS Web 
Client Authentication
I/InputParser(15640):             X509v3 Key Usage: critical
I/InputParser(15640):                 Digital Signature, Key Encipherment
I/InputParser(15640):             X509v3 CRL Distribution Points: 
I/InputParser(15640): 
I/InputParser(15640):                 Full Name:
I/InputParser(15640):                   URI:http://crl.godaddy.com/gds3-50.crl
I/InputParser(15640): 
I/InputParser(15640):             X509v3 Certificate Policies: 
I/InputParser(15640):                 Policy: 2.16.840.1.114413.1.7.23.3
I/InputParser(15640):                   CPS: 
http://certificates.godaddy.com/repository/
I/InputParser(15640): 
I/InputParser(15640):             Authority Information Access: 
I/InputParser(15640):                 OCSP - URI:http://ocsp.godaddy.com/
I/InputParser(15640):                 CA Issuers - 
URI:http://certificates.godaddy.com/repository/gd_intermediate.crt
I/InputParser(15640): 
I/InputParser(15640):             X509v3 Authority Key Identifier: 
I/InputParser(15640):                 
keyid:FD:AC:61:32:93:6C:45:D6:E2:EE:85:5F:9A:BA:E7:76:99:68:CC:E7
I/InputParser(15640): 
I/InputParser(15640):             X509v3 Subject Alternative Name: 
I/InputParser(15640):                 DNS:bitpay.com, DNS:www.bitpay.com
I/InputParser(15640):             X509v3 Subject Key Identifier: 
I/InputParser(15640):                 
3A:06:4D:99:B6:C8:B5:0A:65:8B:45:65:E0:27:5C:75:9C:D6:28:47
I/InputParser(15640):     Signature Algorithm: sha1WithRSAEncryption
I/InputParser(15640):          
26:09:02:15:da:aa:a5:d9:b0:4f:0b:73:35:27:e1:b0:fe:69:
I/InputParser(15640):          
6d:6e:84:23:bd:e3:14:a8:ae:1d:3d:13:5f:a4:58:98:ab:14:
I/InputParser(15640):          
f5:4f:8b:08:a5:bf:ca:c7:e2:eb:9a:a0:94:5f:d5:a5:a7:c5:
I/InputParser(15640):          
ec:1c:3d:61:fd:d2:52:7c:0a:63:0c:aa:9d:f6:d1:8d:88:97:
I/InputParser(15640):          
17:58:fa:a2:6a:7a:b3:e6:a9:a7:dd:db:59:48:d7:7c:f4:05:
I/InputParser(15640):          
84:8a:fa:da:19:4f:32:b2:8c:40:81:52:c8:93:cb:34:ba:69:
I/InputParser(15640):          
e7:5c:ad:21:e6:5b:68:c8:e2:92:6c:16:f3:c6:ae:c4:44:c3:
I/InputParser(15640):          
85:bf:7f:85:c1:cf:b9:ce:0b:67:04:e5:d3:a9:52:68:72:dc:
I/InputParser(15640):          
54:46:c5:01:a5:32:ca:1b:51:82:8b:99:e6:de:b8:6a:13:4c:
I/InputParser(15640):          
db:72:8c:8a:f8:5e:75:82:23:21:85:48:b8:28:73:24:1c:8d:
I/InputParser(15640):          
d7:b5:a7:78:51:a7:8d:41:ac:60:f2:af:95:e7:26:5f:30:12:
I/InputParser(15640):          
8c:26:fc:3d:4e:e2:aa:89:30:66:53:eb:9d:3d:3d:c7:45:8b:
I/InputParser(15640):          
ab:d7:c2:f4:74:4a:6d:2e:63:ea:48:4a:ae:3e:94:33:da:38:
I/InputParser(15640):          
45:c2:a7:4b:5b:37:ec:64:3d:fa:b2:fa:d7:b4:6f:b0:99:28:
I/InputParser(15640):          20:6d:23:0d
I/InputParser(15640): 
I/InputParser(15640): [backgroundThread] - certificate length: 2065
I/InputParser(15640): [backgroundThread] - signature length: 256

Here is the snippet of code that I use to print the certificate chain:

final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
final Protos.X509Certificates certificates = 
Protos.X509Certificates.newBuilder().mergeFrom(paymentRequest.getPkiData()).buil
d();
for (final ByteString certificate : certificates.getCertificateList())
{
    final InputStream in = certificate.newInput();
    final X509Certificate cert = (X509Certificate) certFactory.generateCertificate(in);
    log.info(cert.toString());
    log.info("- certificate length: " + certificate.size());
}

Original issue reported on code.google.com by andreas....@gmail.com on 13 Feb 2014 at 8:44

GoogleCodeExporter commented 9 years ago
The issue was that the cert chain was only partially included with the request. 
After this was changed by Bitpay, we get the following error:

java.security.cert.CertPathValidatorException: Version 1 certificates
can't be used as CA ones

I'm adding the cert chain again, this time as a file attachment.

+cc Kevin, because you wrote the original payment protocol implementation. Can 
you say if we can fix this issue on the App/bitcoinj side?

Original comment by andreas....@gmail.com on 14 Feb 2014 at 4:26

Attachments:

GoogleCodeExporter commented 9 years ago
One way I can make it more robust is to fall back to the bitcoinj trust store 
if the system store doesn't contain the cert we are looking for. That may or 
may not solve the problem, but it would still be an improvement regardless.

Original comment by kgree...@gmail.com on 16 Feb 2014 at 12:49

GoogleCodeExporter commented 9 years ago
Oh I misunderstood the issue. Well here is the relevant code in the 
CertPathValidator (search for "as CA ones"):
http://bouncycastle.sourcearchive.com/documentation/1.39/src_2org_2bouncycastle_
2jce_2provider_2PKIXCertPathValidatorSpi_8java-source.html

It explicitly throws that exception if the version of any of the certs in the 
chain equals 1. I don't think there is anything we can do about it on the 
bitcoinj side.

The problem is that the last cert in the attached cert chain is version 1.

Original comment by kgree...@gmail.com on 16 Feb 2014 at 1:06

GoogleCodeExporter commented 9 years ago
What's the issue about "version 1" certs? Can the issue be fixed by just 
omitting that last cert?

BitPay already stated they won't change the root certificate anytime soon.

Original comment by andreas....@gmail.com on 16 Feb 2014 at 9:14

GoogleCodeExporter commented 9 years ago
I just tried Bitpay again, and the error message now is 
"PaymentRequestException$PkiVerificationException: Invalid signature, this 
payment request is not valid."

I'm not sure what they've been trying, I did not get an e-mail update yet.

Original comment by andreas....@gmail.com on 16 Feb 2014 at 6:29

GoogleCodeExporter commented 9 years ago
BitPay payment requests are validating for some time now. It must have been an 
issue on their end.

Original comment by mh.in.en...@gmail.com on 2 Mar 2014 at 12:01