package org.cacert.gigi.pages.account;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
import java.io.PrintWriter;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
import java.sql.SQLException;
+import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import org.cacert.gigi.Language;
import org.cacert.gigi.User;
import org.cacert.gigi.Certificate.CSRType;
+import org.cacert.gigi.crypto.SPKAC;
import org.cacert.gigi.output.Form;
import org.cacert.gigi.output.template.HashAlgorithms;
import org.cacert.gigi.output.template.IterableDataset;
import org.cacert.gigi.util.RandomToken;
import sun.security.pkcs10.PKCS10;
+import sun.security.util.DerInputStream;
+import sun.security.util.DerValue;
+import sun.security.x509.AlgorithmId;
/**
* This class represents a form that is used for issuing certificates. This
String csr = req.getParameter("CSR");
String spkac = req.getParameter("SPKAC");
try {
- if (csr != null) {
- PKCS10 parsed = parseCSR(csr);
- out.println(parsed.getSubjectName().getCommonName());
- out.println(parsed.getSubjectName().getCountry());
- out.println("CSR DN: " + parsed.getSubjectName() + "<br/>");
- PublicKey pk = parsed.getSubjectPublicKeyInfo();
- out.println("Type: " + pk.getAlgorithm() + "<br/>");
- if (pk instanceof RSAPublicKey) {
- out.println("Exponent: " + ((RSAPublicKey) pk).getPublicExponent() + "<br/>");
- out.println("Length: " + ((RSAPublicKey) pk).getModulus().bitLength());
- } else if (pk instanceof DSAPublicKey) {
- DSAPublicKey dpk = (DSAPublicKey) pk;
- out.println("Length: " + dpk.getY().bitLength() + "<br/>");
- out.println(dpk.getParams());
- } else if (pk instanceof ECPublicKey) {
- ECPublicKey epk = (ECPublicKey) pk;
- out.println("Length-x: " + epk.getW().getAffineX().bitLength() + "<br/>");
- out.println("Length-y: " + epk.getW().getAffineY().bitLength() + "<br/>");
- out.println(epk.getParams().getCurve());
- }
- out.println("<br/>digest: sha256<br/>");
- this.csr = csr;
- this.csrType = CSRType.CSR;
- } else if (spkac != null) {
- String cleanedSPKAC = "SPKAC=" + spkac.replaceAll("[\r\n]", "");
- try {
- checkSPKAC(cleanedSPKAC, spkacChallange);
- this.csr = cleanedSPKAC;
+ try {
+ if (csr != null) {
+ byte[] data = PEM.decode("(NEW )?CERTIFICATE REQUEST", csr);
+ PKCS10 parsed = new PKCS10(data);
+
+ out.println(parsed.getSubjectName().getCommonName());
+ out.println(parsed.getSubjectName().getCountry());
+ out.println("CSR DN: " + parsed.getSubjectName() + "<br/>");
+ PublicKey pk = parsed.getSubjectPublicKeyInfo();
+ checkKeyStrength(pk, out);
+ String sign = getSignatureAlgorithm(data);
+ out.println("<br/>digest: " + sign + "<br/>");
+
+ this.csr = csr;
+ this.csrType = CSRType.CSR;
+ } else if (spkac != null) {
+ String cleanedSPKAC = spkac.replaceAll("[\r\n]", "");
+ byte[] data = Base64.getDecoder().decode(cleanedSPKAC);
+ SPKAC parsed = new SPKAC(data);
+ if ( !parsed.getChallenge().equals(spkacChallange)) {
+ throw new GigiApiException("Challange mismatch");
+ }
+ checkKeyStrength(parsed.getPubkey(), out);
+ String sign = getSignatureAlgorithm(data);
+ out.println("<br/>digest: " + sign + "<br/>");
+
+ // spkacChallange
+ this.csr = "SPKAC=" + cleanedSPKAC;
this.csrType = CSRType.SPKAC;
- } catch (GigiApiException e) {
- e.format(out, Page.getLanguage(req));
- }
- } else {
- login = "1".equals(req.getParameter("login"));
- String hashAlg = req.getParameter("hash_alg");
- if (hashAlg != null) {
- selectedDigest = Digest.valueOf(hashAlg);
- }
- if (req.getParameter("CCA") == null) {
- outputError(out, req, "You need to accept the CCA.");
- return false;
- }
- System.out.println("issuing " + selectedDigest);
- result = new Certificate(LoginPage.getUser(req).getId(), "/commonName=CAcert WoT User", selectedDigest.toString(), this.csr, this.csrType);
- try {
+ } else {
+ login = "1".equals(req.getParameter("login"));
+ String hashAlg = req.getParameter("hash_alg");
+ if (hashAlg != null) {
+ selectedDigest = Digest.valueOf(hashAlg);
+ }
+ if (req.getParameter("CCA") == null) {
+ outputError(out, req, "You need to accept the CCA.");
+ return false;
+ }
+ System.out.println("issuing " + selectedDigest);
+ result = new Certificate(LoginPage.getUser(req).getId(), "/commonName=CAcert WoT User", selectedDigest.toString(), this.csr, this.csrType);
result.issue().waitFor(60000);
return true;
- } catch (SQLException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
- e.printStackTrace();
}
- return false;
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ throw new GigiApiException("Certificate Request format is invalid.");
+ } catch (GeneralSecurityException e) {
+ throw new GigiApiException("Certificate Request format is invalid.");
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (SQLException e) {
+ throw new GigiApiException(e);
}
- } catch (IOException e) {
- e.printStackTrace();
- } catch (GeneralSecurityException e) {
- e.printStackTrace();
+ } catch (GigiApiException e) {
+ e.format(out, Page.getLanguage(req));
}
return false;
}
- private static void checkSPKAC(String csr, String spkacChallange) throws IOException, GigiApiException {
- Process p = Runtime.getRuntime().exec(new String[] {
- "openssl", "spkac", "-verify"
- });
- OutputStream outputStream = p.getOutputStream();
- outputStream.write(csr.getBytes());
- outputStream.flush();
- outputStream.close();
- BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream(), "UTF-8"));
- String line;
- String challenge = null;
- while ((line = br.readLine()) != null) {
- line = line.trim();
- String challengePrefix = "Challenge String: ";
- if (line.startsWith(challengePrefix)) {
- challenge = line.substring(challengePrefix.length());
- }
- }
- GigiApiException gae = new GigiApiException();
- if ( !spkacChallange.equals(challenge)) {
- gae.mergeInto(new GigiApiException("The challenge-response code of your certificate request did not match. Can't continue with certificaterequest."));
- }
- try {
- if (p.waitFor() != 0) {
- gae.mergeInto(new GigiApiException("The signature of your certificate request is invalid. Can't continue with certificaterequest."));
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- if ( !gae.isEmpty()) {
- throw gae;
+ private void checkKeyStrength(PublicKey pk, PrintWriter out) {
+ out.println("Type: " + pk.getAlgorithm() + "<br/>");
+ if (pk instanceof RSAPublicKey) {
+ out.println("Exponent: " + ((RSAPublicKey) pk).getPublicExponent() + "<br/>");
+ out.println("Length: " + ((RSAPublicKey) pk).getModulus().bitLength());
+ } else if (pk instanceof DSAPublicKey) {
+ DSAPublicKey dpk = (DSAPublicKey) pk;
+ out.println("Length: " + dpk.getY().bitLength() + "<br/>");
+ out.println(dpk.getParams());
+ } else if (pk instanceof ECPublicKey) {
+ ECPublicKey epk = (ECPublicKey) pk;
+ out.println("Length-x: " + epk.getW().getAffineX().bitLength() + "<br/>");
+ out.println("Length-y: " + epk.getW().getAffineY().bitLength() + "<br/>");
+ out.println(epk.getParams().getCurve());
}
}
- private PKCS10 parseCSR(String csr) throws IOException, GeneralSecurityException {
+ private static PKCS10 parseCSR(String csr) throws IOException, GeneralSecurityException {
return new PKCS10(PEM.decode("(NEW )?CERTIFICATE REQUEST", csr));
}
+ private static String getSignatureAlgorithm(byte[] data) throws IOException {
+ DerInputStream in = new DerInputStream(data);
+ DerValue[] seq = in.getSequence(3);
+ return AlgorithmId.parse(seq[1]).getName();
+ }
+
@Override
public void output(PrintWriter out, Language l, Map<String, Object> vars) {
if (csr == null) {