3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-12 02:05:53 +00:00

Payment protocol: misc enhancements.

Stop using the JDK store and use our own, to make the StartSSL fix effective.
Include the certs in the exception thrown if the chain doesn't verify.
Support loading from a file in the PaymentProtocol tool.
Print the certs out in the PaymentProtocol tool if there's an error.
This commit is contained in:
Mike Hearn 2014-03-23 19:21:42 +01:00
parent feecc8f486
commit 0ed260bae2
3 changed files with 45 additions and 10 deletions

View File

@ -16,6 +16,9 @@
package com.google.bitcoin.protocols.payments;
import java.security.cert.X509Certificate;
import java.util.List;
public class PaymentRequestException extends Exception {
public PaymentRequestException(String msg) {
super(msg);
@ -86,6 +89,8 @@ public class PaymentRequestException extends Exception {
}
public static class PkiVerificationException extends PaymentRequestException {
public List<X509Certificate> certificates;
public PkiVerificationException(String msg) {
super(msg);
}
@ -93,5 +98,10 @@ public class PaymentRequestException extends Exception {
public PkiVerificationException(Exception e) {
super(e);
}
public PkiVerificationException(Exception e, List<X509Certificate> certificates) {
super(e);
this.certificates = certificates;
}
}
}

View File

@ -441,6 +441,7 @@ public class PaymentSession {
* Returns null if no PKI method was specified in the {@link Protos.PaymentRequest}.
*/
public @Nullable PkiVerificationData verifyPki() throws PaymentRequestException {
List<X509Certificate> certs = null;
try {
if (pkiVerificationData != null)
return pkiVerificationData;
@ -464,7 +465,7 @@ public class PaymentSession {
// The ordering of certificates is defined by the payment protocol spec to be the same as what the Java
// crypto API requires - convenient!
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
List<X509Certificate> certs = Lists.newArrayList();
certs = Lists.newArrayList();
for (ByteString bytes : protoCerts.getCertificateList())
certs.add((X509Certificate) certificateFactory.generateCertificate(bytes.newInput()));
CertPath path = certificateFactory.generateCertPath(certs);
@ -536,7 +537,7 @@ public class PaymentSession {
} catch (CertPathValidatorException e) {
// The certificate chain isn't known or trusted, probably, the server is using an SSL root we don't
// know about and the user needs to upgrade to a new version of the software (or import a root cert).
throw new PaymentRequestException.PkiVerificationException(e);
throw new PaymentRequestException.PkiVerificationException(e, certs);
} catch (InvalidKeyException e) {
// Shouldn't happen if the certs verified correctly.
throw new PaymentRequestException.PkiVerificationException(e);
@ -586,8 +587,7 @@ public class PaymentSession {
path = System.getProperty("javax.net.ssl.trustStore");
}
if (path == null) {
// Try this default system location for Linux/Windows/OSX.
path = System.getProperty("java.home") + "/lib/security/cacerts".replace('/', File.separatorChar);
return loadFallbackStore(defaultPassword);
}
try {
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
@ -597,13 +597,17 @@ public class PaymentSession {
} catch (FileNotFoundException e) {
// If we failed to find a system trust store, load our own fallback trust store. This can fail on Android
// but we should never reach it there.
KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream is = getClass().getResourceAsStream("cacerts");
keyStore.load(is, defaultPassword);
return keyStore;
return loadFallbackStore(defaultPassword);
}
}
private KeyStore loadFallbackStore(char[] defaultPassword) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
KeyStore keyStore = KeyStore.getInstance("JKS");
InputStream is = getClass().getResourceAsStream("cacerts");
keyStore.load(is, defaultPassword);
return keyStore;
}
private void parsePaymentRequest(Protos.PaymentRequest request) throws PaymentRequestException {
try {
if (request == null)

View File

@ -20,9 +20,14 @@ import com.google.bitcoin.protocols.payments.PaymentRequestException;
import com.google.bitcoin.protocols.payments.PaymentSession;
import com.google.bitcoin.uri.BitcoinURI;
import com.google.bitcoin.uri.BitcoinURIParseException;
import org.bitcoin.protocols.payments.Protos;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.concurrent.ExecutionException;
@ -42,7 +47,12 @@ public class PaymentProtocol {
try {
URI uri = new URI(arg);
PaymentSession session;
if (uri.getScheme().equals("http")) {
if (arg.startsWith("/")) {
FileInputStream stream = new FileInputStream(arg);
Protos.PaymentRequest request = Protos.PaymentRequest.parseFrom(stream);
stream.close();
session = new PaymentSession(request);
} else if (uri.getScheme().equals("http")) {
session = PaymentSession.createFromUrl(arg).get();
} else if (uri.getScheme().equals("bitcoin")) {
BitcoinURI bcuri = new BitcoinURI(arg);
@ -75,13 +85,24 @@ public class PaymentProtocol {
System.err.println("Could not parse URI: " + e.getMessage());
} catch (BitcoinURIParseException e) {
System.err.println("Could not parse URI: " + e.getMessage());
} catch (PaymentRequestException.PkiVerificationException e) {
System.err.println(e.getMessage());
if (e.certificates != null) {
for (X509Certificate certificate : e.certificates) {
System.err.println(" " + certificate);
}
}
} catch (PaymentRequestException e) {
System.err.println("Could not handle payment URL: " + e.getMessage());
System.err.println("Could not handle payment request: " + e.getMessage());
} catch (InterruptedException e) {
System.err.println("Interrupted whilst processing/downloading.");
} catch (ExecutionException e) {
System.err.println("Failed whilst retrieving payment URL: " + e.getMessage());
e.printStackTrace();
} catch (FileNotFoundException e) {
System.err.println(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
}
}
}