X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=util-testing%2Forg%2Fcacert%2Fgigi%2Futil%2FSimpleSigner.java;h=0c36a3bcbbb6a554a14126047217c61d03788aca;hp=d42ec94a00826edd2b14fbc5c8b5c80bc554bef0;hb=3d182aa4e55ec11d9223334f444fa5307585cc94;hpb=23008e75449699a6b65b97e9144e88659bf5b7dd diff --git a/util-testing/org/cacert/gigi/util/SimpleSigner.java b/util-testing/org/cacert/gigi/util/SimpleSigner.java index d42ec94a..0c36a3bc 100644 --- a/util-testing/org/cacert/gigi/util/SimpleSigner.java +++ b/util-testing/org/cacert/gigi/util/SimpleSigner.java @@ -1,6 +1,5 @@ package org.cacert.gigi.util; -import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -14,8 +13,6 @@ import java.math.BigInteger; import java.nio.file.Paths; import java.security.GeneralSecurityException; import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; @@ -28,7 +25,6 @@ import java.sql.SQLException; import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Arrays; import java.util.Base64; import java.util.Calendar; import java.util.Date; @@ -44,9 +40,9 @@ import javax.security.auth.x500.X500Principal; import org.cacert.gigi.crypto.SPKAC; import org.cacert.gigi.database.DatabaseConnection; +import org.cacert.gigi.database.DatabaseConnection.Link; import org.cacert.gigi.database.GigiPreparedStatement; import org.cacert.gigi.database.GigiResultSet; -import org.cacert.gigi.dbObjects.Certificate; import org.cacert.gigi.dbObjects.Certificate.CSRType; import org.cacert.gigi.dbObjects.Certificate.SANType; import org.cacert.gigi.dbObjects.Certificate.SubjectAlternateName; @@ -80,6 +76,8 @@ public class SimpleSigner { private static GigiPreparedStatement finishJob; + private static GigiPreparedStatement locateCA; + private static volatile boolean running = true; private static Thread runner; @@ -92,19 +90,6 @@ public class SimpleSigner { } public static void main(String[] args) throws IOException, SQLException, InterruptedException { - if (false) { - try { - KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); - kpg.initialize(2048); - KeyPair kp = kpg.generateKeyPair(); - X500Principal xp = new X500Principal(genX500Name(Certificate.buildDN("CN", "uiae")).getEncoded()); - byte[] i = generateCert(kp.getPublic(), kp.getPrivate(), Certificate.buildDN("CN", "uiae"), xp, Arrays.asList(), new Date(), new Date(System.currentTimeMillis() + 1000 * 60 * 60), Digest.SHA512, "clientAuth"); - System.out.println(Base64.getMimeEncoder().encodeToString(i)); - } catch (GeneralSecurityException e) { - e.printStackTrace(); - } - return; - } Properties p = new Properties(); try (Reader reader = new InputStreamReader(new FileInputStream("config/gigi.properties"), "UTF-8")) { p.load(reader); @@ -132,34 +117,52 @@ public class SimpleSigner { throw new IllegalStateException("already running"); } running = true; - readyCerts = DatabaseConnection.getInstance().prepare("SELECT certs.id AS id, certs.csr_name, jobs.id AS jobid, csr_type, md, executeFrom, executeTo, profile FROM jobs " + // - "INNER JOIN certs ON certs.id=jobs.targetId " + // - "INNER JOIN profiles ON profiles.id=certs.profile " + // - "WHERE jobs.state='open' "// - + "AND task='sign'"); - getSANSs = DatabaseConnection.getInstance().prepare("SELECT contents, type FROM subjectAlternativeNames " + // - "WHERE certId=?"); + runner = new Thread() { - updateMail = DatabaseConnection.getInstance().prepare("UPDATE certs SET crt_name=?," + " created=NOW(), serial=?, caid=1 WHERE id=?"); - warnMail = DatabaseConnection.getInstance().prepare("UPDATE jobs SET warning=warning+1, state=IF(warning<3, 'open','error') WHERE id=?"); + @Override + public void run() { + try (Link l = DatabaseConnection.newLink(false)) { + readyCerts = new GigiPreparedStatement("SELECT certs.id AS id, certs.csr_name, jobs.id AS jobid, csr_type, md, `executeFrom`, `executeTo`, profile FROM jobs " + // + "INNER JOIN certs ON certs.id=jobs.`targetId` " + // + "INNER JOIN profiles ON profiles.id=certs.profile " + // + "WHERE jobs.state='open' "// + + "AND task='sign'"); - revoke = DatabaseConnection.getInstance().prepare("SELECT certs.id, certs.csr_name,jobs.id FROM jobs INNER JOIN certs ON jobs.targetId=certs.id" + " WHERE jobs.state='open' AND task='revoke'"); - revokeCompleted = DatabaseConnection.getInstance().prepare("UPDATE certs SET revoked=NOW() WHERE id=?"); + getSANSs = new GigiPreparedStatement("SELECT contents, type FROM `subjectAlternativeNames` " + // + "WHERE `certId`=?"); - finishJob = DatabaseConnection.getInstance().prepare("UPDATE jobs SET state='done' WHERE id=?"); + updateMail = new GigiPreparedStatement("UPDATE certs SET crt_name=?," + " created=NOW(), serial=?, caid=? WHERE id=?"); + warnMail = new GigiPreparedStatement("UPDATE jobs SET warning=warning+1, state=IF(warning<3, 'open','error') WHERE id=?"); - runner = new Thread() { + revoke = new GigiPreparedStatement("SELECT certs.id, certs.csr_name,jobs.id FROM jobs INNER JOIN certs ON jobs.`targetId`=certs.id" + " WHERE jobs.state='open' AND task='revoke'"); + revokeCompleted = new GigiPreparedStatement("UPDATE certs SET revoked=NOW() WHERE id=?"); - @Override - public void run() { - work(); + finishJob = new GigiPreparedStatement("UPDATE jobs SET state='done' WHERE id=?"); + + locateCA = new GigiPreparedStatement("SELECT id FROM cacerts WHERE keyname=?"); + + work(); + } catch (InterruptedException e) { + throw new Error(e); + } } }; runner.start(); } + public static void ping() { + synchronized (SimpleSigner.class) { + SimpleSigner.class.notifyAll(); + try { + SimpleSigner.class.wait(2000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + private synchronized static void work() { try { gencrl(); @@ -174,6 +177,7 @@ public class SimpleSigner { signCertificates(); revokeCertificates(); + SimpleSigner.class.notifyAll(); SimpleSigner.class.wait(5000); } catch (IOException e) { e.printStackTrace(); @@ -190,8 +194,8 @@ public class SimpleSigner { boolean worked = false; while (rs.next()) { int id = rs.getInt(1); - File crt = KeyStorage.locateCrt(id); worked = true; + System.out.println("Revoke faked: " + id); revokeCompleted.setInt(1, id); revokeCompleted.execute(); finishJob.setInt(1, rs.getInt(3)); @@ -207,7 +211,8 @@ public class SimpleSigner { return; } String[] call = new String[] { - "openssl", "ca",// + "openssl", + "ca",// "-cert", "../unassured.crt",// "-keyfile", @@ -227,8 +232,6 @@ public class SimpleSigner { } } - private static int counter = 0; - private static void signCertificates() throws SQLException { GigiResultSet rs = readyCerts.executeQuery(); @@ -269,10 +272,8 @@ public class SimpleSigner { getSANSs.setInt(1, id); GigiResultSet san = getSANSs.executeQuery(); - boolean first = true; LinkedList altnames = new LinkedList<>(); while (san.next()) { - first = false; altnames.add(new SubjectAlternateName(SANType.valueOf(san.getString("type").toUpperCase()), san.getString("contents"))); } // TODO look them up! @@ -289,19 +290,21 @@ public class SimpleSigner { } s += "-" + cp.getKeyName() + ".cfg"; Properties caP = new Properties(); - caP.load(new FileInputStream("signer/profiles/" + s)); - String ca = caP.getProperty("ca") + "_2015_1"; + try (FileInputStream inStream = new FileInputStream("signer/profiles/" + s)) { + caP.load(inStream); + } HashMap subj = new HashMap<>(); - GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT name, value FROM certAvas WHERE certId=?"); - ps.setInt(1, rs.getInt("id")); - GigiResultSet rs2 = ps.executeQuery(); - while (rs2.next()) { - String name = rs2.getString("name"); - if (name.equals("EMAIL")) { - name = "emailAddress"; + try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT name, value FROM `certAvas` WHERE `certId`=?")) { + ps.setInt(1, rs.getInt("id")); + GigiResultSet rs2 = ps.executeQuery(); + while (rs2.next()) { + String name = rs2.getString("name"); + if (name.equals("EMAIL")) { + name = "emailAddress"; + } + subj.put(name, rs2.getString("value")); } - subj.put(name, rs2.getString("value")); } if (subj.size() == 0) { subj.put("CN", ""); @@ -312,21 +315,29 @@ public class SimpleSigner { PublicKey pk; byte[] data = IOUtils.readURL(new FileInputStream(csrname)); if (ct == CSRType.SPKAC) { - String dt = new String(data); + String dt = new String(data, "UTF-8"); if (dt.startsWith("SPKAC=")) { dt = dt.substring(6); - data = dt.getBytes(); + data = dt.getBytes("UTF-8"); System.out.println(dt); } SPKAC sp = new SPKAC(Base64.getDecoder().decode(data)); pk = sp.getPubkey(); } else { - PKCS10 p10 = new PKCS10(PEM.decode("(NEW )?CERTIFICATE REQUEST", new String(data))); + PKCS10 p10 = new PKCS10(PEM.decode("(NEW )?CERTIFICATE REQUEST", new String(data, "UTF-8"))); pk = p10.getSubjectPublicKeyInfo(); } - PrivateKey i = loadOpensslKey(new File("signer/ca/" + ca + "/ca.key")); + String ca = caP.getProperty("ca") + "_2015_1"; + File parent = new File("signer/ca"); + for (File f : parent.listFiles()) { + if (f.getName().startsWith(caP.getProperty("ca"))) { + ca = f.getName(); + break; + } + } + File caKey = new File(parent, ca + "/ca.key"); + PrivateKey i = loadOpensslKey(caKey); - String[] call; X509Certificate root = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(new FileInputStream("signer/ca/" + ca + "/ca.crt")); byte[] cert = generateCert(pk, i, subj, root.getSubjectX500Principal(), altnames, fromDate, toDate, Digest.valueOf(rs.getString("md").toUpperCase()), caP.getProperty("eku")); PrintWriter out = new PrintWriter(crt); @@ -334,27 +345,21 @@ public class SimpleSigner { out.println(Base64.getMimeEncoder().encodeToString(cert)); out.println("-----END CERTIFICATE-----"); out.close(); - synchronized (sdf) { - /* - * call = new String[] { "openssl", "ca",// "-in", "../../" - * + csrname,// "-cert", "../" + ca + ".crt",// "-keyfile", - * "../" + ca + ".key",// "-out", "../../" + - * crt.getPath(),// "-utf8", "-startdate", - * sdf.format(fromDate),// "-enddate", sdf.format(toDate),// - * "-batch",// "-md", rs.getString("md"),// "-extfile", - * "../" + f.getName(),// "-subj", - * Certificate.stringifyDN(subj),// "-config", - * "../selfsign.config"// }; - */ - } try (InputStream is = new FileInputStream(crt)) { + locateCA.setString(1, ca); + GigiResultSet caRs = locateCA.executeQuery(); + if ( !caRs.next()) { + throw new Error("ca " + ca + " was not found"); + } + CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate crtp = (X509Certificate) cf.generateCertificate(is); BigInteger serial = crtp.getSerialNumber(); updateMail.setString(1, crt.getPath()); updateMail.setString(2, serial.toString(16)); - updateMail.setInt(3, id); + updateMail.setInt(3, caRs.getInt("id")); + updateMail.setInt(4, id); updateMail.execute(); finishJob.setInt(1, rs.getInt("jobid")); @@ -394,12 +399,12 @@ public class SimpleSigner { return i; } - private static synchronized byte[] generateCert(PublicKey pk, PrivateKey prk, Map subj, X500Principal issuer, List altnames, Date fromDate, Date toDate, Digest digest, String eku) throws IOException, GeneralSecurityException { + public static synchronized byte[] generateCert(PublicKey pk, PrivateKey prk, Map subj, X500Principal issuer, List altnames, Date fromDate, Date toDate, Digest digest, String eku) throws IOException, GeneralSecurityException { File f = Paths.get("signer", "serial").toFile(); if ( !f.exists()) { - FileOutputStream fos = new FileOutputStream(f); - fos.write("1".getBytes()); - fos.close(); + try (FileOutputStream fos = new FileOutputStream(f)) { + fos.write("1".getBytes("UTF-8")); + } } try (FileInputStream fr = new FileInputStream(f)) { byte[] serial = IOUtils.readURL(fr); @@ -475,20 +480,25 @@ public class SimpleSigner { contentSeq.putBitString(s.sign()); cert.write(DerValue.tag_Sequence, contentSeq); - X509Certificate c = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(new ByteArrayInputStream(cert.toByteArray())); + // X509Certificate c = (X509Certificate) + // CertificateFactory.getInstance("X509").generateCertificate(new + // ByteArrayInputStream(cert.toByteArray())); // c.verify(pk); only for self-signeds - return cert.toByteArray(); + byte[] res = cert.toByteArray(); + cert.close(); + return res; } } private static byte[] generateKU() throws IOException { - DerOutputStream dos = new DerOutputStream(); - dos.putBitString(new byte[] { - (byte) 0b10101000 - }); - return dos.toByteArray(); + try (DerOutputStream dos = new DerOutputStream()) { + dos.putBitString(new byte[] { + (byte) 0b10101000 + }); + return dos.toByteArray(); + } } private static byte[] generateEKU(String eku) throws IOException { @@ -509,6 +519,9 @@ public class SimpleSigner { case "emailProtection": oid = new ObjectIdentifier("1.3.6.1.5.5.7.3.4"); break; + case "OCSPSigning": + oid = new ObjectIdentifier("1.3.6.1.5.5.7.3.9"); + break; default: throw new Error(name); @@ -521,7 +534,7 @@ public class SimpleSigner { return dos.toByteArray(); } - private static X500Name genX500Name(Map subj) throws IOException { + public static X500Name genX500Name(Map subj) throws IOException { LinkedList rdns = new LinkedList<>(); for (Entry i : subj.entrySet()) { RDN rdn = genRDN(i); @@ -557,10 +570,27 @@ public class SimpleSigner { 2, 5, 4, 11 }; break; + case "ST": + oid = new int[] { + 2, 5, 4, 8 + }; + break; + case "L": + oid = new int[] { + 2, 5, 4, 7 + }; + break; + case "C": + oid = new int[] { + 2, 5, 4, 6 + }; + break; default: + dos.close(); throw new Error("unknown RDN-type: " + key); } RDN rdn = new RDN(new AVA(new ObjectIdentifier(oid), new DerValue(dos.toByteArray()))); + dos.close(); return rdn; } @@ -581,13 +611,16 @@ public class SimpleSigner { } else if (san.getType() == SANType.EMAIL) { type = (byte) GeneralNameInterface.NAME_RFC822; } else { + SANContent.close(); throw new Error("" + san.getType()); } - SANContent.write(DerValue.createTag(DerValue.TAG_CONTEXT, false, type), san.getName().getBytes()); + SANContent.write(DerValue.createTag(DerValue.TAG_CONTEXT, false, type), san.getName().getBytes("UTF-8")); } DerOutputStream SANSeqContent = new DerOutputStream(); SANSeqContent.write(DerValue.tag_Sequence, SANContent); byte[] byteArray = SANSeqContent.toByteArray(); + SANContent.close(); + SANSeqContent.close(); return byteArray; } }