Changeset 886dbf1 for core


Ignore:
Timestamp:
Oct 28, 2016 1:39:01 AM (4 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
4f0cae5
Parents:
0439206
Message:

Crypto: Generate more-conforming selfsigned certs (ticket #1853)

Location:
core/java/src/net/i2p/crypto
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/i2p/crypto/KeyStoreUtil.java

    r0439206 r886dbf1  
    598598                throw new IOException("Can't create directory " + dir);
    599599        }
    600         Object[] rv = SelfSignedGenerator.generate(cname, ou, "XX", "I2P Anonymous Network", "XX", "XX", validDays, type);
     600        Object[] rv = SelfSignedGenerator.generate(cname, ou, null, "I2P Anonymous Network", null, null, validDays, type);
    601601        PublicKey jpub = (PublicKey) rv[0];
    602602        PrivateKey jpriv = (PrivateKey) rv[1];
  • core/java/src/net/i2p/crypto/SelfSignedGenerator.java

    r0439206 r886dbf1  
    6262    // Subject Key Identifier
    6363    private static final String OID_SKI = "2.5.29.14";
     64    // Key Usage
     65    private static final String OID_USAGE = "2.5.29.15";
     66    // Subject Alternative Name
     67    private static final String OID_SAN = "2.5.29.17";
     68    // Basic Constraints
     69    private static final String OID_BASIC = "2.5.29.19";
    6470    // CRL number
    6571    private static final String OID_CRLNUM = "2.5.29.20";
     72    // Authority Key Identifier
     73    private static final String OID_AKI = "2.5.29.35";
    6674
    6775    private static final Map<String, String> OIDS;
    6876    static {
    6977        OIDS = new HashMap<String, String>(16);
     78        // only OIDs in the distinguished name need to be in here
    7079        OIDS.put(OID_CN, "CN");
    7180        OIDS.put(OID_C, "C");
     
    7483        OIDS.put(OID_O, "O");
    7584        OIDS.put(OID_OU, "OU");
    76         OIDS.put(OID_SKI, "SKI");
    77     }
    78 
    79     /**
     85    }
     86
     87    /**
     88     *  @param cname the common name, non-null
     89     *  @param ou The OU (organizational unit) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
     90     *  @param o The O (organization)in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
     91     *  @param l The L (city or locality) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
     92     *  @param st The ST (state or province) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
     93     *  @param c The C (country) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
     94     *
     95     *  @return length 4 array:
    8096     *  rv[0] is a Java PublicKey
    8197     *  rv[1] is a Java PrivateKey
     
    236252    }
    237253
     254    /**
     255     *  @param cname the common name, non-null
     256     *  @param ou The OU (organizational unit) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
     257     *  @param o The O (organization)in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
     258     *  @param l The L (city or locality) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
     259     *  @param st The ST (state or province) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
     260     *  @param c The C (country) in the distinguished name, non-null before 0.9.28, may be null as of 0.9.28
     261     */
    238262    private static byte[] genTBS(String cname, String ou, String o, String l, String st, String c,
    239263                          int validDays, byte[] sigoid, PublicKey jpub) throws GeneralSecurityException {
     
    249273
    250274        // going to use this for both issuer and subject
    251         String dname = "CN=" + cname + ",OU=" + ou + ",O=" + o + ",L=" + l + ",ST=" + st + ",C=" + c;
     275        StringBuilder buf = new StringBuilder(128);
     276        buf.append("CN=").append(cname);
     277        if (ou != null)
     278            buf.append(",OU=").append(ou);
     279        if (o != null)
     280            buf.append(",O=").append(o);
     281        if (l != null)
     282            buf.append(",L=").append(l);
     283        if (st != null)
     284            buf.append(",ST=").append(st);
     285        if (c != null)
     286            buf.append(",C=").append(c);
     287        String dname = buf.toString();
    252288        byte[] issuer = (new X500Principal(dname, OIDS)).getEncoded();
    253289        byte[] validity = getValidity(validDays);
     
    255291
    256292        byte[] pubbytes = jpub.getEncoded();
    257         byte[] extbytes = getExtensions(pubbytes);
     293        byte[] extbytes = getExtensions(pubbytes, cname);
    258294
    259295        int len = version.length + serial.length + sigoid.length + issuer.length +
     
    437473
    438474    /**
     475     *  Add the following extensions:
     476     *   1) Subject Key Identifier
     477     *   2) Key Usage
     478     *   3) Basic Constraints
     479     *   4) Subject Alternative Name
     480     *   5) Authority Key Identifier
     481     *  (not necessarily output in that order)
     482     *
     483     *  Ref: RFC 5280
    439484     *
    440485     *  @param pubbytes bit string
    441      *  @return 35 bytes ASN.1 encoded object
    442      */
    443     private static byte[] getExtensions(byte[] pubbytes) {
     486     *  @return ASN.1 encoded object
     487     */
     488    private static byte[] getExtensions(byte[] pubbytes, String cname) {
    444489        // RFC 2549 sec. 4.2.1.2
    445490        // subject public key identifier is the sha1 hash of the bit string of the public key
     
    453498        md.update(pubbytes, pidx, pubbytes.length - pidx);
    454499        byte[] sha = md.digest();
    455         byte[] oid = getEncodedOID(OID_SKI);
    456 
    457         int wraplen = spaceFor(sha.length);
    458         int extlen = oid.length + spaceFor(wraplen);
    459         int extslen = spaceFor(extlen);
     500        byte[] oid1 = getEncodedOID(OID_SKI);
     501        byte[] oid2 = getEncodedOID(OID_USAGE);
     502        byte[] oid3 = getEncodedOID(OID_BASIC);
     503        byte[] oid4 = getEncodedOID(OID_SAN);
     504        byte[] oid5 = getEncodedOID(OID_AKI);
     505        byte[] TRUE = new byte[] { 1, 1, (byte) 0xff };
     506
     507        int wrap1len = spaceFor(sha.length);
     508        int ext1len = oid1.length + spaceFor(wrap1len);
     509
     510        int wrap2len = 4;
     511        int ext2len = oid2.length + TRUE.length + spaceFor(wrap2len);
     512
     513        int wrap3len = spaceFor(TRUE.length);
     514        int ext3len = oid3.length + TRUE.length + spaceFor(wrap3len);
     515
     516        byte[] cnameBytes = DataHelper.getASCII(cname);
     517        int wrap41len = spaceFor(cnameBytes.length);
     518        int wrap4len = spaceFor(wrap41len);
     519        int ext4len = oid4.length + spaceFor(wrap4len);
     520
     521        int wrap51len = wrap1len;
     522        int wrap5len = spaceFor(wrap51len);
     523        int ext5len = oid5.length + spaceFor(wrap5len);
     524
     525        int extslen = spaceFor(ext1len) + spaceFor(ext2len) + spaceFor(ext3len) + spaceFor(ext4len) + spaceFor(ext5len);
    460526        int seqlen = spaceFor(extslen);
    461527        int totlen = spaceFor(seqlen);
    462528        byte[] rv = new byte[totlen];
    463529        int idx = 0;
     530
    464531        rv[idx++] = (byte) 0xa3;
    465532        idx = intToASN1(rv, idx, seqlen);
    466533        rv[idx++] = (byte) 0x30;
    467534        idx = intToASN1(rv, idx, extslen);
    468         rv[idx++] = (byte) 0x30;
    469         idx = intToASN1(rv, idx, extlen);
    470         System.arraycopy(oid, 0, rv, idx, oid.length);
    471         idx += oid.length;
    472         // don't know why we wrap the octet string in an octet string
     535
     536        // Subject Key Identifier
     537        rv[idx++] = (byte) 0x30;
     538        idx = intToASN1(rv, idx, ext1len);
     539        System.arraycopy(oid1, 0, rv, idx, oid1.length);
     540        idx += oid1.length;
     541        // octet string wraps an octet string
    473542        rv[idx++] = (byte) 0x04;
    474         idx = intToASN1(rv, idx, wraplen);
     543        idx = intToASN1(rv, idx, wrap1len);
    475544        rv[idx++] = (byte) 0x04;
    476545        idx = intToASN1(rv, idx, sha.length);
    477546        System.arraycopy(sha, 0, rv, idx, sha.length);
     547        idx += sha.length;
     548
     549        // Authority Key Identifier
     550        rv[idx++] = (byte) 0x30;
     551        idx = intToASN1(rv, idx, ext5len);
     552        System.arraycopy(oid5, 0, rv, idx, oid5.length);
     553        idx += oid5.length;
     554        // octet string wraps a sequence containing a choice 0 (key identifier) byte string
     555        rv[idx++] = (byte) 0x04;
     556        idx = intToASN1(rv, idx, wrap5len);
     557        rv[idx++] = (byte) 0x30;
     558        idx = intToASN1(rv, idx, wrap51len);
     559        rv[idx++] = (byte) 0x80; // choice
     560        idx = intToASN1(rv, idx, sha.length);
     561        System.arraycopy(sha, 0, rv, idx, sha.length);
     562        idx += sha.length;
     563
     564        // Basic Constraints (critical)
     565        rv[idx++] = (byte) 0x30;
     566        idx = intToASN1(rv, idx, ext3len);
     567        System.arraycopy(oid3, 0, rv, idx, oid3.length);
     568        idx += oid3.length;
     569        System.arraycopy(TRUE, 0, rv, idx, TRUE.length);
     570        idx += TRUE.length;
     571        // octet string wraps an sequence containing TRUE
     572        rv[idx++] = (byte) 0x04;
     573        idx = intToASN1(rv, idx, wrap3len);
     574        rv[idx++] = (byte) 0x30;
     575        idx = intToASN1(rv, idx, TRUE.length);
     576        System.arraycopy(TRUE, 0, rv, idx, TRUE.length);
     577        idx += TRUE.length;
     578
     579        // Key Usage (critical)
     580        rv[idx++] = (byte) 0x30;
     581        idx = intToASN1(rv, idx, ext2len);
     582        System.arraycopy(oid2, 0, rv, idx, oid2.length);
     583        idx += oid2.length;
     584        System.arraycopy(TRUE, 0, rv, idx, TRUE.length);
     585        idx += TRUE.length;
     586        // octet string wraps a bit string
     587        rv[idx++] = (byte) 0x04;
     588        idx = intToASN1(rv, idx, wrap2len);
     589        rv[idx++] = (byte) 0x03;
     590        rv[idx++] = (byte) 0x02;
     591        rv[idx++] = (byte) 0x01;
     592        rv[idx++] = (byte) 0xa6; // sig, key encipherment, cert, CRL
     593
     594        // Subject Alternative Name
     595        rv[idx++] = (byte) 0x30;
     596        idx = intToASN1(rv, idx, ext4len);
     597        System.arraycopy(oid4, 0, rv, idx, oid4.length);
     598        idx += oid4.length;
     599        // octet string wraps a sequence containing a choice 2 (DNSName) IA5String
     600        rv[idx++] = (byte) 0x04;
     601        idx = intToASN1(rv, idx, wrap4len);
     602        rv[idx++] = (byte) 0x30;
     603        idx = intToASN1(rv, idx, wrap41len);
     604        rv[idx++] = (byte) 0x82; // choice, IA5String implied
     605        idx = intToASN1(rv, idx, cnameBytes.length);
     606        System.arraycopy(cnameBytes, 0, rv, idx, cnameBytes.length);
     607        idx += cnameBytes.length;
     608
    478609        return rv;
    479610    }
     
    580711
    581712    private static final void test(String name, SigType type) throws Exception {
    582             Object[] rv = generate("cname", "ou", "l", "o", "st", "c", 3652, type);
     713            Object[] rv = generate("cname.example.com", "ou", "o", null, "st", "c", 3652, type);
    583714            PublicKey jpub = (PublicKey) rv[0];
    584715            PrivateKey jpriv = (PrivateKey) rv[1];
Note: See TracChangeset for help on using the changeset viewer.