Crypto: Consolidate certificate import methods

This commit is contained in:
zzz
2015-12-08 02:07:38 +00:00
parent 9ba5ad7bb1
commit 8b42896cc6
4 changed files with 64 additions and 61 deletions

View File

@@ -1,11 +1,16 @@
package net.i2p.crypto;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Locale;
@@ -134,4 +139,40 @@ public class CertUtil {
Log l = ctx.logManager().getLog(CertUtil.class);
l.log(level, msg, t);
}
/**
* Get the Java public key from a X.509 certificate file.
* Throws if the certificate is invalid (e.g. expired).
*
* @return non-null, throws on all errors including certificate invalid
* @since 0.9.24 moved from SU3File private method
*/
public static PublicKey loadKey(File kd) throws IOException, GeneralSecurityException {
return loadCert(kd).getPublicKey();
}
/**
* Get the certificate from a X.509 certificate file.
* Throws if the certificate is invalid (e.g. expired).
*
* @return non-null, throws on all errors including certificate invalid
* @since 0.9.24 adapted from SU3File private method
*/
public static X509Certificate loadCert(File kd) throws IOException, GeneralSecurityException {
InputStream fis = null;
try {
fis = new FileInputStream(kd);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);
cert.checkValidity();
return cert;
} catch (IllegalArgumentException iae) {
// java 1.8.0_40-b10, openSUSE
// Exception in thread "main" java.lang.IllegalArgumentException: Input byte array has wrong 4-byte ending unit
// at java.util.Base64$Decoder.decode0(Base64.java:704)
throw new GeneralSecurityException("cert error", iae);
} finally {
try { if (fis != null) fis.close(); } catch (IOException foo) {}
}
}
}

View File

@@ -35,6 +35,8 @@ class DirKeyRing implements KeyRing {
* and have a CN == keyName.
*
* CN check unsupported on Android.
*
* @return null if file doesn't exist, throws on all other errors
*/
public PublicKey getKey(String keyName, String scope, SigType type)
throws GeneralSecurityException, IOException {
@@ -47,26 +49,15 @@ class DirKeyRing implements KeyRing {
File kd = new File(sd, fileName + ".crt");
if (!kd.exists())
return null;
InputStream fis = null;
try {
fis = new FileInputStream(kd);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);
cert.checkValidity();
if (!SystemVersion.isAndroid()) {
// getSubjectValue() unsupported on Android.
// Any cert problems will be caught in non-Android testing.
String cn = CertUtil.getSubjectValue(cert, "CN");
if (!keyName.equals(cn))
throw new GeneralSecurityException("CN mismatch: " + cn);
}
return cert.getPublicKey();
} catch (IllegalArgumentException iae) {
// java 1.8.0_40-b10, openSUSE
throw new GeneralSecurityException("Bad cert", iae);
} finally {
try { if (fis != null) fis.close(); } catch (IOException foo) {}
X509Certificate cert = CertUtil.loadCert(kd);
if (!SystemVersion.isAndroid()) {
// getSubjectValue() unsupported on Android.
// Any cert problems will be caught in non-Android testing.
String cn = CertUtil.getSubjectValue(cert, "CN");
if (!keyName.equals(cn))
throw new GeneralSecurityException("CN mismatch: " + cn);
}
return cert.getPublicKey();
}
/**

View File

@@ -12,7 +12,6 @@ import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.Locale;
@@ -317,46 +316,32 @@ public class KeyStoreUtil {
* @since 0.8.2, moved from SSLEepGet in 0.9.9
*/
public static boolean addCert(File file, String alias, KeyStore ks) {
InputStream fis = null;
try {
fis = new FileInputStream(file);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);
X509Certificate cert = CertUtil.loadCert(file);
info("Read X509 Certificate from " + file.getAbsolutePath() +
" Issuer: " + cert.getIssuerX500Principal() +
" Serial: " + cert.getSerialNumber().toString(16) +
"; Valid From: " + cert.getNotBefore() +
" To: " + cert.getNotAfter());
try {
cert.checkValidity();
} catch (CertificateExpiredException cee) {
String s = "Rejecting expired X509 Certificate: " + file.getAbsolutePath();
// Android often has old system certs
if (SystemVersion.isAndroid())
warn(s, cee);
else
error(s, cee);
return false;
} catch (CertificateNotYetValidException cnyve) {
error("Rejecting X509 Certificate not yet valid: " + file.getAbsolutePath(), cnyve);
return false;
}
ks.setCertificateEntry(alias, cert);
info("Now trusting X509 Certificate, Issuer: " + cert.getIssuerX500Principal());
} catch (CertificateExpiredException cee) {
String s = "Rejecting expired X509 Certificate: " + file.getAbsolutePath();
// Android often has old system certs
if (SystemVersion.isAndroid())
warn(s, cee);
else
error(s, cee);
return false;
} catch (CertificateNotYetValidException cnyve) {
error("Rejecting X509 Certificate not yet valid: " + file.getAbsolutePath(), cnyve);
return false;
} catch (GeneralSecurityException gse) {
error("Error reading X509 Certificate: " + file.getAbsolutePath(), gse);
return false;
} catch (IOException ioe) {
error("Error reading X509 Certificate: " + file.getAbsolutePath(), ioe);
return false;
} catch (IllegalArgumentException iae) {
// java 1.8.0_40-b10, openSUSE
// Exception in thread "main" java.lang.IllegalArgumentException: Input byte array has wrong 4-byte ending unit
// at java.util.Base64$Decoder.decode0(Base64.java:704)
error("Error reading X509 Certificate: " + file.getAbsolutePath(), iae);
return false;
} finally {
try { if (fis != null) fis.close(); } catch (IOException foo) {}
}
return true;
}

View File

@@ -15,8 +15,6 @@ import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
@@ -978,24 +976,12 @@ public class SU3File {
* @since 0.9.15
*/
private static PublicKey loadKey(File kd) throws IOException {
InputStream fis = null;
try {
fis = new FileInputStream(kd);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate)cf.generateCertificate(fis);
cert.checkValidity();
return cert.getPublicKey();
return CertUtil.loadKey(kd);
} catch (GeneralSecurityException gse) {
IOException ioe = new IOException("cert error");
ioe.initCause(gse);
throw ioe;
} catch (IllegalArgumentException iae) {
// java 1.8.0_40-b10, openSUSE
IOException ioe = new IOException("cert error");
ioe.initCause(iae);
throw ioe;
} finally {
try { if (fis != null) fis.close(); } catch (IOException foo) {}
}
}
}