Changeset 2f7eb56


Ignore:
Timestamp:
Feb 17, 2014 1:29:41 PM (7 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
6e0ca92
Parents:
45997fd (diff), 8c98ef73 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

propagate from branch 'i2p.i2p.zzz.ecdsa' (head e83bcdc842f5995d310a4295147f9326a993e010)

to branch 'i2p.i2p' (head 4983f716f8740bc7ddfae5561a562a0d42a815ae)

Files:
1 added
33 edited

Legend:

Unmodified
Added
Removed
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java

    r45997fd r2f7eb56  
    13971397
    13981398    /**
    1399      * Generate a new keypair
     1399     * Generate a new keypair.
     1400     * Does NOT support non-default sig types.
    14001401     * Deprecated - only used by CLI
    14011402     *
     
    14401441
    14411442    /**
    1442      * Generate a new keypair
     1443     * Generate a new keypair.
     1444     * Does NOT support non-default sig types.
    14431445     * Deprecated - only used by CLI
    14441446     *
     
    14491451     */
    14501452    private static void runGenTextKeys(Logging l) {
    1451         ByteArrayOutputStream privkey = new ByteArrayOutputStream(512);
     1453        ByteArrayOutputStream privkey = new ByteArrayOutputStream(1024);
    14521454        ByteArrayOutputStream pubkey = new ByteArrayOutputStream(512);
    14531455        makeKey(privkey, pubkey, l);
     
    16951697    /**
    16961698     * Create a new destination, storing the destination and its private keys where
    1697      * instructed
     1699     * instructed.
     1700     * Does NOT support non-default sig types.
    16981701     * Deprecated - only used by CLI
    16991702     *
    1700      * @param writeTo location to store the private keys
     1703     * @param writeTo location to store the destination and private keys
    17011704     * @param pubDest location to store the destination
    17021705     * @param l logger to send messages to
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/TunnelController.java

    r45997fd r2f7eb56  
    88import java.util.Map;
    99import java.util.Properties;
     10
    1011import net.i2p.I2PAppContext;
    1112import net.i2p.I2PException;
     
    1314import net.i2p.client.I2PClientFactory;
    1415import net.i2p.client.I2PSession;
     16import net.i2p.crypto.SigType;
    1517import net.i2p.data.Base32;
    1618import net.i2p.data.Destination;
     
    5052     * before being interpreted by this controller)
    5153     *
    52      * @param config original key=value mapping
    53      * @param prefix beginning of key values that are relevent to this tunnel
     54     * @param config original key=value mapping non-null
     55     * @param prefix beginning of key values that are relevant to this tunnel
    5456     */
    5557    public TunnelController(Properties config, String prefix) {
     
    5961    /**
    6062     *
     63     * @param config original key=value mapping non-null
     64     * @param prefix beginning of key values that are relevant to this tunnel
    6165     * @param createKey for servers, whether we want to create a brand new destination
    6266     *                  with private keys at the location specified or not (does not
     
    100104        try {
    101105            fos = new SecureFileOutputStream(keyFile);
    102             Destination dest = client.createDestination(fos);
     106            SigType stype = I2PClient.DEFAULT_SIGTYPE;
     107            String st = _config.getProperty("option." + I2PClient.PROP_SIGTYPE);
     108            if (st != null) {
     109                SigType type = SigType.parseSigType(st);
     110                if (type != null)
     111                    stype = type;
     112                else
     113                    log("Unsupported sig type " + st);
     114            }
     115            Destination dest = client.createDestination(fos, stype);
    103116            String destStr = dest.toBase64();
    104117            log("Private key created and saved in " + keyFile.getAbsolutePath());
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java

    r45997fd r2f7eb56  
    1313import net.i2p.client.I2PSession;
    1414import net.i2p.client.I2PSessionException;
     15import net.i2p.crypto.SigType;
    1516import net.i2p.data.Destination;
    1617import net.i2p.i2ptunnel.I2PTunnel;
     
    7980        byte[] key;
    8081        try {
    81             ByteArrayOutputStream out = new ByteArrayOutputStream(512);
    82             client.createDestination(out);
     82            ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
     83            SigType stype = I2PClient.DEFAULT_SIGTYPE;
     84            String st = tunnel.getClientOptions().getProperty(I2PClient.PROP_SIGTYPE);
     85            if (st != null) {
     86                SigType type = SigType.parseSigType(st);
     87                if (type != null)
     88                    stype = type;
     89                else
     90                    l.log("Unsupported sig type " + st);
     91            }
     92            client.createDestination(out, stype);
    8393            key = out.toByteArray();
    8494        } catch(Exception exc) {
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/EditBean.java

    r45997fd r2f7eb56  
    1515import java.util.TreeMap;
    1616
     17import net.i2p.client.I2PClient;
    1718import net.i2p.data.Base64;
    1819import net.i2p.data.Destination;
     
    178179    }
    179180   
     181    /** @since 0.9.12 */
     182    public int getSigType(int tunnel) {
     183        return getProperty(tunnel, I2PClient.PROP_SIGTYPE, 0);
     184    }
     185   
    180186    /** @since 0.8.9 */
    181187    public boolean getDCC(int tunnel) {
     
    357363    public Set<String> interfaceSet() {
    358364        return Addresses.getAllAddresses();
     365    }
     366
     367    /** @since 0.9.12 */
     368    public boolean isAdvanced() {
     369        return _context.getBooleanProperty("routerconsole.advanced");
    359370    }
    360371
  • apps/i2ptunnel/java/src/net/i2p/i2ptunnel/web/IndexBean.java

    r45997fd r2f7eb56  
    2525import net.i2p.app.ClientAppManager;
    2626import net.i2p.app.Outproxy;
     27import net.i2p.client.I2PClient;
    2728import net.i2p.data.Base32;
    2829import net.i2p.data.Certificate;
     
    984985        }
    985986    }
     987
    986988    public void setCert(String val) {
    987989        if (val != null) {
     
    991993        }
    992994    }
     995
    993996    public void setSigner(String val) {
    994997        _certSigner = val;
     998    }
     999
     1000    /** @since 0.9.12 */
     1001    public void setSigType(String val) {
     1002        if (val != null) {
     1003            _otherOptions.put(I2PClient.PROP_SIGTYPE, val);
     1004            if (val.equals("0"))
     1005                _certType = 0;
     1006            else
     1007                _certType = 5;
     1008        }
     1009        // TODO: Call modifyDestination??
     1010        // Otherwise this only works on a new tunnel...
    9951011    }
    9961012
     
    12351251        I2PTunnelHTTPClient.PROP_JUMP_SERVERS,
    12361252        I2PTunnelHTTPClientBase.PROP_AUTH,
     1253        I2PClient.PROP_SIGTYPE,
    12371254        I2PTunnelHTTPClient.PROP_SSL_OUTPROXIES
    12381255        };
     
    12411258         PROP_MAX_CONNS_MIN, PROP_MAX_CONNS_HOUR, PROP_MAX_CONNS_DAY,
    12421259         PROP_MAX_TOTAL_CONNS_MIN, PROP_MAX_TOTAL_CONNS_HOUR, PROP_MAX_TOTAL_CONNS_DAY,
    1243          PROP_MAX_STREAMS
     1260         PROP_MAX_STREAMS, I2PClient.PROP_SIGTYPE
    12441261        };
    12451262    private static final String _httpServerOpts[] = {
  • apps/i2ptunnel/jsp/editClient.jsp

    r45997fd r2f7eb56  
    450450         <% } %>
    451451           
     452         <% if (editBean.isAdvanced()) { %>
     453            <div id="tunnelOptionsField" class="rowItem">
     454                <label>
     455                    <%=intl._("Signature type")%>
     456                    (<%=intl._("Experts only!")%>)
     457                </label>
     458            </div>
     459            <div id="hostField" class="rowItem">
     460              <div id="portField" class="rowItem">
     461                <label>DSA-SHA1</label>
     462                <input value="0" type="radio" id="startOnLoad" name="sigType" title="Default"<%=(editBean.getSigType(curTunnel)==0 ? " checked=\"checked\"" : "")%> class="tickbox" />               
     463              </div>
     464              <div id="portField" class="rowItem">
     465                <label>ECDSA-P256</label>
     466                <input value="1" type="radio" id="startOnLoad" name="sigType" title="Advanced users only"<%=(editBean.getSigType(curTunnel)==1 ? " checked=\"checked\"" : "")%> class="tickbox" />               
     467              </div>
     468              <div id="portField" class="rowItem">
     469                <label>ECDSA-P384</label>
     470                <input value="2" type="radio" id="startOnLoad" name="sigType" title="Advanced users only"<%=(editBean.getSigType(curTunnel)==2 ? " checked=\"checked\"" : "")%> class="tickbox" />               
     471              </div>
     472              <div id="portField" class="rowItem">
     473                <label>ECDSA-P521</label>
     474                <input value="3" type="radio" id="startOnLoad" name="sigType" title="Advanced users only"<%=(editBean.getSigType(curTunnel)==3 ? " checked=\"checked\"" : "")%> class="tickbox" />               
     475              </div>
     476            </div>
     477                 
     478            <div class="subdivider">
     479                <hr />
     480            </div>
     481         <% } // isAdvanced %>>
     482
    452483         <% if ("httpclient".equals(tunnelType) || "connectclient".equals(tunnelType) || "sockstunnel".equals(tunnelType) || "socksirctunnel".equals(tunnelType)) { %>
    453484            <div id="accessField" class="rowItem">
  • apps/i2ptunnel/jsp/editServer.jsp

    r45997fd r2f7eb56  
    492492            </div>
    493493           
     494<% /***************** %>
    494495            <div id="tunnelOptionsField" class="rowItem">
    495496                <label for="cert" accesskey="c">
     
    534535                <span class="comment"><%=intl._("(Tunnel must be stopped first)")%></span>
    535536            </div>
     537<% **********************/ %>
     538
     539         <% if (editBean.isAdvanced()) { %>
     540            <div id="tunnelOptionsField" class="rowItem">
     541                <label>
     542                    <%=intl._("Signature type")%>
     543                    (<%=intl._("Experts only! Changes B32!")%>)
     544                </label>
     545            </div>
     546            <div id="hostField" class="rowItem">
     547              <div id="portField" class="rowItem">
     548                <label>DSA-SHA1</label>
     549                <input value="0" type="radio" id="startOnLoad" name="sigType" title="Default"<%=(editBean.getSigType(curTunnel)==0 ? " checked=\"checked\"" : "")%> class="tickbox" />               
     550              </div>
     551              <div id="portField" class="rowItem">
     552                <label>ECDSA-P256</label>
     553                <input value="1" type="radio" id="startOnLoad" name="sigType" title="Advanced users only"<%=(editBean.getSigType(curTunnel)==1 ? " checked=\"checked\"" : "")%> class="tickbox" />               
     554              </div>
     555              <div id="portField" class="rowItem">
     556                <label>ECDSA-P384</label>
     557                <input value="2" type="radio" id="startOnLoad" name="sigType" title="Advanced users only"<%=(editBean.getSigType(curTunnel)==2 ? " checked=\"checked\"" : "")%> class="tickbox" />               
     558              </div>
     559              <div id="portField" class="rowItem">
     560                <label>ECDSA-P521</label>
     561                <input value="3" type="radio" id="startOnLoad" name="sigType" title="Advanced users only"<%=(editBean.getSigType(curTunnel)==3 ? " checked=\"checked\"" : "")%> class="tickbox" />               
     562              </div>
     563            </div>
    536564                 
    537565            <div class="subdivider">
    538566                <hr />
    539567            </div>
     568         <% } // isAdvanced %>>
    540569                 
    541570            <div id="customOptionsField" class="rowItem">
  • apps/ministreaming/java/src/net/i2p/client/streaming/I2PSocketManagerFactory.java

    r45997fd r2f7eb56  
    1515import net.i2p.client.I2PSession;
    1616import net.i2p.client.I2PSessionException;
     17import net.i2p.crypto.SigType;
    1718import net.i2p.util.Log;
    1819
     
    2728    public static final String PROP_MANAGER = "i2p.streaming.manager";
    2829    public static final String DEFAULT_MANAGER = "net.i2p.client.streaming.impl.I2PSocketManagerFull";
    29    
     30
    3031    /**
    3132     * Create a socket manager using a brand new destination connected to the
     
    8081    public static I2PSocketManager createManager(String i2cpHost, int i2cpPort, Properties opts) {
    8182        I2PClient client = I2PClientFactory.createClient();
    82         ByteArrayOutputStream keyStream = new ByteArrayOutputStream(512);
     83        ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024);
    8384        try {
    84             client.createDestination(keyStream);
     85            client.createDestination(keyStream, getSigType(opts));
    8586            ByteArrayInputStream in = new ByteArrayInputStream(keyStream.toByteArray());
    8687            return createManager(in, i2cpHost, i2cpPort, opts);
     
    169170        if (myPrivateKeyStream == null) {
    170171            I2PClient client = I2PClientFactory.createClient();
    171             ByteArrayOutputStream keyStream = new ByteArrayOutputStream(512);
     172            ByteArrayOutputStream keyStream = new ByteArrayOutputStream(1024);
    172173            try {
    173                 client.createDestination(keyStream);
     174                client.createDestination(keyStream, getSigType(opts));
    174175            } catch (Exception e) {
    175176                throw new I2PSessionException("Error creating keys", e);
     
    258259    }
    259260
     261    /**
     262     *  @param opts may be null
     263     *  @since 0.9.12
     264     */
     265    private static SigType getSigType(Properties opts) {
     266        if (opts != null) {
     267            String st = opts.getProperty(I2PClient.PROP_SIGTYPE);
     268            if (st != null) {
     269                SigType rv = SigType.parseSigType(st);
     270                if (rv != null)
     271                    return rv;
     272                getLog().error("Unsupported sig type " + st);
     273            }
     274        }
     275        return I2PClient.DEFAULT_SIGTYPE;
     276    }
     277
    260278    /** @since 0.9.7 */
    261279    private static Log getLog() {
  • apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java

    r45997fd r2f7eb56  
    2424import java.util.TreeSet;
    2525
     26import net.i2p.data.Base32;
    2627import net.i2p.data.DataHelper;
    2728import net.i2p.data.Destination;
     
    168169                }
    169170                buf.append(" Dist: <b>").append(fmt.format(biLog2(dist))).append("</b><br>");
     171                buf.append(Base32.encode(key.getData())).append(".b32.i2p<br>");
     172                buf.append("Sig type: ").append(dest.getSigningPublicKey().getType()).append("<br>");
    170173                buf.append("Routing Key: ").append(ls.getRoutingKey().toBase64());
    171174                buf.append("<br>");
  • apps/streaming/java/src/net/i2p/client/streaming/impl/Packet.java

    r45997fd r2f7eb56  
    66
    77import net.i2p.I2PAppContext;
     8import net.i2p.crypto.SigType;
    89import net.i2p.data.Base64;
    910import net.i2p.data.ByteArray;
     
    404405     */
    405406    public int writePacket(byte buffer[], int offset) throws IllegalStateException {
    406         return writePacket(buffer, offset, true);
    407     }
    408     /**
    409      * @param includeSig if true, include the real signature, otherwise put zeroes
    410      *                   in its place.
    411      */
    412     private int writePacket(byte buffer[], int offset, boolean includeSig) throws IllegalStateException {
     407        return writePacket(buffer, offset, 0);
     408    }
     409
     410    /**
     411     * @param fakeSigLen if 0, include the real signature in _optionSignature;
     412     *                   if nonzero, leave space for that many bytes
     413     */
     414    private int writePacket(byte buffer[], int offset, int fakeSigLen) throws IllegalStateException {
    413415        int cur = offset;
    414416        DataHelper.toLong(buffer, cur, 4, (_sendStreamId >= 0 ? _sendStreamId : STREAM_ID_UNKNOWN));
     
    444446        if (isFlagSet(FLAG_MAX_PACKET_SIZE_INCLUDED))
    445447            optionSize += 2;
    446         if (isFlagSet(FLAG_SIGNATURE_INCLUDED))
    447             optionSize += Signature.SIGNATURE_BYTES;
     448        if (isFlagSet(FLAG_SIGNATURE_INCLUDED)) {
     449            if (fakeSigLen > 0)
     450                optionSize += fakeSigLen;
     451            else if (_optionSignature != null)
     452                optionSize += _optionSignature.length();
     453            else
     454                throw new IllegalStateException();
     455        }
    448456       
    449457        DataHelper.toLong(buffer, cur, 2, optionSize);
     
    462470        }
    463471        if (isFlagSet(FLAG_SIGNATURE_INCLUDED)) {
    464             if (includeSig)
    465                 System.arraycopy(_optionSignature.getData(), 0, buffer, cur, Signature.SIGNATURE_BYTES);
    466             else // we're signing (or validating)
    467                 Arrays.fill(buffer, cur, cur+Signature.SIGNATURE_BYTES, (byte)0x0);
    468             cur += Signature.SIGNATURE_BYTES;
     472            if (fakeSigLen == 0) {
     473                // we're signing (or validating)
     474                System.arraycopy(_optionSignature.getData(), 0, buffer, cur, _optionSignature.length());
     475                cur += _optionSignature.length();
     476            } else {
     477                Arrays.fill(buffer, cur, cur + fakeSigLen, (byte)0x0);
     478                cur += fakeSigLen;
     479            }
    469480        }
    470481       
     
    519530            size += 2;
    520531        if (isFlagSet(FLAG_SIGNATURE_INCLUDED))
    521             size += Signature.SIGNATURE_BYTES;
     532            size += _optionSignature.length();
    522533       
    523534        size += 2; // option size
     
    614625        }
    615626        if (isFlagSet(FLAG_SIGNATURE_INCLUDED)) {
    616             Signature optionSignature = new Signature();
    617             byte buf[] = new byte[Signature.SIGNATURE_BYTES];
    618             System.arraycopy(buffer, cur, buf, 0, Signature.SIGNATURE_BYTES);
     627            Signature optionSignature;
     628            Destination from = getOptionalFrom();
     629            if (from != null) {
     630                optionSignature = new Signature(from.getSigningPublicKey().getType());
     631            } else {
     632                // super cheat for now, look for correct type,
     633                // assume no more options. If we add to the options
     634                // we will have to ask the manager.
     635                int siglen = payloadBegin - cur;
     636                SigType type = null;
     637                for (SigType t : SigType.values()) {
     638                    if (t.getSigLen() == siglen) {
     639                        type = t;
     640                        break;
     641                    }
     642                }
     643                if (type == null) {
     644                    if (siglen < Signature.SIGNATURE_BYTES)
     645                        throw new IllegalArgumentException("unknown sig type len=" + siglen);
     646                    // Hope it's the default type with some unknown options following;
     647                    // if not the sig will fail later
     648                    type = SigType.DSA_SHA1;
     649                    siglen = Signature.SIGNATURE_BYTES;
     650                }
     651                optionSignature = new Signature(type);
     652            }
     653            byte buf[] = new byte[optionSignature.length()];
     654            System.arraycopy(buffer, cur, buf, 0, buf.length);
    619655            optionSignature.setData(buf);
    620656            setOptionalSignature(optionSignature);
    621             cur += Signature.SIGNATURE_BYTES;
     657            cur += buf.length;
    622658        }
    623659    }
     
    642678        if (buffer == null)
    643679            buffer = new byte[size];
    644         int written = writePacket(buffer, 0, false);
     680        int written = writePacket(buffer, 0, from.getSigningPublicKey().getType().getSigLen());
    645681        if (written != size) {
    646682            ctx.logManager().getLog(Packet.class).error("Written " + written + " size " + size + " for " + toString(), new Exception("moo"));
     
    673709    public int writeSignedPacket(byte buffer[], int offset, I2PAppContext ctx, SigningPrivateKey key) throws IllegalStateException {
    674710        setFlag(FLAG_SIGNATURE_INCLUDED);
    675         int size = writePacket(buffer, offset, false);
     711        int size = writePacket(buffer, offset, key.getType().getSigLen());
    676712        _optionSignature = ctx.dsa().sign(buffer, offset, size, key);
    677         if (false) {
    678             Log l = ctx.logManager().getLog(Packet.class);
    679             l.error("Signing: " + toString());
    680             l.error(Base64.encode(buffer, 0, size));
    681             l.error("Signature: " + Base64.encode(_optionSignature.getData()));
    682         }
     713        //if (false) {
     714        //    Log l = ctx.logManager().getLog(Packet.class);
     715        //    l.error("Signing: " + toString());
     716        //    l.error(Base64.encode(buffer, 0, size));
     717        //    l.error("Signature: " + Base64.encode(_optionSignature.getData()));
     718        //}
    683719        // jump into the signed data and inject the signature where we
    684720        // previously placed a bunch of zeroes
     
    695731                              + (isFlagSet(FLAG_FROM_INCLUDED) ? _optionFrom.size() : 0)
    696732                              + (isFlagSet(FLAG_MAX_PACKET_SIZE_INCLUDED) ? 2 : 0);
    697         System.arraycopy(_optionSignature.getData(), 0, buffer, signatureOffset, Signature.SIGNATURE_BYTES);
     733        System.arraycopy(_optionSignature.getData(), 0, buffer, signatureOffset, _optionSignature.length());
    698734        return size;
    699735    }
     
    741777        if (isFlagSet(FLAG_DELAY_REQUESTED)) buf.append(" DELAY ").append(_optionDelay);
    742778        if (isFlagSet(FLAG_ECHO)) buf.append(" ECHO");
    743         if (isFlagSet(FLAG_FROM_INCLUDED)) buf.append(" FROM");
     779        if (isFlagSet(FLAG_FROM_INCLUDED)) buf.append(" FROM ").append(_optionFrom.size());
    744780        if (isFlagSet(FLAG_MAX_PACKET_SIZE_INCLUDED)) buf.append(" MS ").append(_optionMaxSize);
    745781        if (isFlagSet(FLAG_PROFILE_INTERACTIVE)) buf.append(" INTERACTIVE");
  • apps/susidns/src/java/src/i2p/susi/dns/AddressBean.java

    r45997fd r2f7eb56  
    3030
    3131import net.i2p.I2PAppContext;
     32import net.i2p.crypto.SigType;
    3233import net.i2p.data.Base32;
    3334import net.i2p.data.Base64;
     
    229230                        case Certificate.CERTIFICATE_TYPE_SIGNED:
    230231                                return _("Signed");
     232                        case Certificate.CERTIFICATE_TYPE_KEY:
     233                                return _("Key");
    231234                        default:
    232235                                return _("Type {0}", type);
    233236                }
     237        }
     238
     239        /**
     240         * Do this the easy way
     241         * @since 0.9.12
     242         */
     243        public String getSigType() {
     244                // (4 / 3) * (pubkey length + signing key length)
     245                String cert = destination.substring(512);
     246                if (cert.equals("AAAA"))
     247                        return _("DSA 1024 bit");
     248                byte[] enc = Base64.decode(cert);
     249                if (enc == null)
     250                        // shouldn't happen
     251                        return "invalid";
     252                int type = enc[0] & 0xff;
     253                if (type != Certificate.CERTIFICATE_TYPE_KEY)
     254                        return _("DSA 1024 bit");
     255                int st = ((enc[3] & 0xff) << 8) | (enc[4] & 0xff);
     256                if (st == 0)
     257                        return _("DSA 1024 bit");
     258                SigType stype = SigType.getByCode(st);
     259                if (stype == null)
     260                        return _("Type {0}", st);
     261                return stype.toString();
    234262        }
    235263
  • apps/susidns/src/jsp/details.jsp

    r45997fd r2f7eb56  
    108108</tr><tr class="list${book.trClass}">
    109109<td><%=intl._("Signing Key")%></td>
    110 <td><%=intl._("DSA 1024 bit")%></td>
     110<td><%=addr.getSigType()%></td>
    111111</tr><tr class="list${book.trClass}">
    112112<td><%=intl._("Certificate")%></td>
  • core/java/src/net/i2p/client/I2PClient.java

    r45997fd r2f7eb56  
    1616
    1717import net.i2p.I2PException;
     18import net.i2p.crypto.SigType;
    1819import net.i2p.data.Certificate;
    1920import net.i2p.data.Destination;
     
    4041    /** @since 0.8.1 */
    4142    public final static String PROP_RELIABILITY_NONE = "none";
     43
     44    /** @since 0.9.12 */
     45    public static final String PROP_SIGTYPE = "i2cp.destination.sigType";
     46    /** @since 0.9.12 */
     47    public static final SigType DEFAULT_SIGTYPE = SigType.DSA_SHA1;
    4248
    4349    /**
     
    8490    public Destination createDestination(OutputStream destKeyStream) throws I2PException, IOException;
    8591
     92    /**
     93     * Create a destination with the given signature type.
     94     * It will have a null certificate for DSA 1024/160 and KeyCertificate otherwise.
     95     * This is not bound to the I2PClient, you must supply the data back again
     96     * in createSession().
     97     *
     98     * @param destKeyStream location to write out the destination, PrivateKey, and SigningPrivateKey,
     99     *                      format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
     100     * @since 0.9.12
     101     */
     102    public Destination createDestination(OutputStream destKeyStream, SigType type) throws I2PException, IOException;
     103
    86104    /** Create a new destination with the given certificate and store it, along with the private
    87105     * encryption and signing keys at the specified location
  • core/java/src/net/i2p/client/I2PClientImpl.java

    r45997fd r2f7eb56  
    1313import java.io.InputStream;
    1414import java.io.OutputStream;
     15import java.security.GeneralSecurityException;
    1516import java.util.Properties;
    1617
     
    1819import net.i2p.I2PException;
    1920import net.i2p.crypto.KeyGenerator;
     21import net.i2p.crypto.SigType;
    2022import net.i2p.data.Certificate;
    2123import net.i2p.data.Destination;
     24import net.i2p.data.KeyCertificate;
    2225import net.i2p.data.PrivateKey;
    2326import net.i2p.data.PublicKey;
    2427import net.i2p.data.SigningPrivateKey;
    2528import net.i2p.data.SigningPublicKey;
     29import net.i2p.data.SimpleDataStructure;
     30import net.i2p.util.RandomSource;
    2631
    2732/**
     
    3540
    3641    /**
    37      * Create the destination with a null payload.
     42     * Create a destination with a DSA 1024/160 signature type and a null certificate.
    3843     * This is not bound to the I2PClient, you must supply the data back again
    3944     * in createSession().
     
    4348     */
    4449    public Destination createDestination(OutputStream destKeyStream) throws I2PException, IOException {
    45         Certificate cert = new Certificate();
    46         cert.setCertificateType(Certificate.CERTIFICATE_TYPE_NULL);
    47         cert.setPayload(null);
     50        return createDestination(destKeyStream, DEFAULT_SIGTYPE);
     51    }
     52
     53    /**
     54     * Create a destination with the given signature type.
     55     * It will have a null certificate for DSA 1024/160 and KeyCertificate otherwise.
     56     * This is not bound to the I2PClient, you must supply the data back again
     57     * in createSession().
     58     *
     59     * @param destKeyStream location to write out the destination, PrivateKey, and SigningPrivateKey,
     60     *                      format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
     61     * @since 0.9.12
     62     */
     63    public Destination createDestination(OutputStream destKeyStream, SigType type) throws I2PException, IOException {
     64        Certificate cert;
     65        if (type == SigType.DSA_SHA1) {
     66            cert = Certificate.NULL_CERT;
     67        } else {
     68            cert = new KeyCertificate(type);
     69        }
    4870        return createDestination(destKeyStream, cert);
    4971    }
     
    5375     * the PrivateKey and SigningPrivateKey to the destKeyStream
    5476     *
     77     * If cert is a KeyCertificate, the signing keypair will be of the specified type.
     78     * The KeyCertificate data must be .............................
     79     * The padding if any will be randomized. The extra key data if any will be set in the
     80     * key cert.
     81     *
    5582     * @param destKeyStream location to write out the destination, PrivateKey, and SigningPrivateKey,
    5683     *                      format is specified in {@link net.i2p.data.PrivateKeyFile PrivateKeyFile}
     
    5885    public Destination createDestination(OutputStream destKeyStream, Certificate cert) throws I2PException, IOException {
    5986        Destination d = new Destination();
    60         d.setCertificate(cert);
    6187        Object keypair[] = KeyGenerator.getInstance().generatePKIKeypair();
    6288        PublicKey publicKey = (PublicKey) keypair[0];
    6389        PrivateKey privateKey = (PrivateKey) keypair[1];
    64         Object signingKeys[] = KeyGenerator.getInstance().generateSigningKeypair();
     90        SimpleDataStructure signingKeys[];
     91        if (cert.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
     92            KeyCertificate kcert = cert.toKeyCertificate();
     93            SigType type = kcert.getSigType();
     94            try {
     95                signingKeys = KeyGenerator.getInstance().generateSigningKeys(type);
     96            } catch (GeneralSecurityException gse) {
     97                throw new I2PException("keygen fail", gse);
     98            }
     99        } else {
     100            signingKeys = KeyGenerator.getInstance().generateSigningKeys();
     101        }
    65102        SigningPublicKey signingPubKey = (SigningPublicKey) signingKeys[0];
    66103        SigningPrivateKey signingPrivKey = (SigningPrivateKey) signingKeys[1];
    67104        d.setPublicKey(publicKey);
    68105        d.setSigningPublicKey(signingPubKey);
     106        if (cert.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
     107            // fix up key certificate or padding
     108            KeyCertificate kcert = cert.toKeyCertificate();
     109            SigType type = kcert.getSigType();
     110            int len = type.getPubkeyLen();
     111            if (len < 128) {
     112                byte[] pad = new byte[128 - len];
     113                RandomSource.getInstance().nextBytes(pad);
     114                d.setPadding(pad);
     115            } else if (len > 128) {
     116                System.arraycopy(signingPubKey.getData(), 128, kcert.getPayload(), KeyCertificate.HEADER_LENGTH, len - 128);
     117            }
     118        }
     119        d.setCertificate(cert);
    69120
    70121        d.writeBytes(destKeyStream);
  • core/java/src/net/i2p/client/I2PSessionImpl.java

    r45997fd r2f7eb56  
    6868    private final PrivateKey _privateKey;
    6969    /** private key for signing */
    70     private final SigningPrivateKey _signingPrivateKey;
     70    private   /* final */  SigningPrivateKey _signingPrivateKey;
    7171    /** configuration options */
    7272    private final Properties _options;
     
    391391        _myDestination.readBytes(destKeyStream);
    392392        _privateKey.readBytes(destKeyStream);
     393        _signingPrivateKey = new SigningPrivateKey(_myDestination.getSigningPublicKey().getType());
    393394        _signingPrivateKey.readBytes(destKeyStream);
    394395    }
  • core/java/src/net/i2p/client/I2PSimpleClient.java

    r45997fd r2f7eb56  
    1313import net.i2p.I2PAppContext;
    1414import net.i2p.I2PException;
     15import net.i2p.crypto.SigType;
    1516import net.i2p.data.Certificate;
    1617import net.i2p.data.Destination;
     
    2122 */
    2223public class I2PSimpleClient implements I2PClient {
    23     /** @deprecated Don't do this */
     24
     25    /**
     26     *  @deprecated Don't do this
     27     *  @throws UnsupportedOperationException always
     28     */
    2429    public Destination createDestination(OutputStream destKeyStream) throws I2PException, IOException {
    25         return null;
     30        throw new UnsupportedOperationException();
    2631    }
    2732
    28     /** @deprecated or this */
     33    /**
     34     *  @deprecated Don't do this
     35     *  @throws UnsupportedOperationException always
     36     *  @since 0.9.12
     37     */
     38    public Destination createDestination(OutputStream destKeyStream, SigType type) throws I2PException, IOException {
     39        throw new UnsupportedOperationException();
     40    }
     41
     42    /**
     43     *  @deprecated Don't do this
     44     *  @throws UnsupportedOperationException always
     45     */
    2946    public Destination createDestination(OutputStream destKeyStream, Certificate cert) throws I2PException, IOException {
    30         return null;
     47        throw new UnsupportedOperationException();
    3148    }
    3249
     
    3855        return createSession(I2PAppContext.getGlobalContext(), options);
    3956    }
     57
    4058    /**
    4159     * Create a new session (though do not connect it yet)
  • core/java/src/net/i2p/client/RequestLeaseSetMessageHandler.java

    r45997fd r2f7eb56  
    1515import net.i2p.I2PAppContext;
    1616import net.i2p.crypto.KeyGenerator;
     17import net.i2p.crypto.SigType;
    1718import net.i2p.data.DataFormatException;
    1819import net.i2p.data.DataHelper;
     
    106107        try {
    107108            leaseSet.sign(session.getPrivateKey());
     109            // Workaround for unparsable serialized signing private key for revocation
     110            // Send him a dummy DSA_SHA1 private key since it's unused anyway
     111            // See CreateLeaseSetMessage.doReadMessage()
     112            SigningPrivateKey spk = li.getSigningPrivateKey();
     113            if (!_context.isRouterContext() && spk.getType() != SigType.DSA_SHA1) {
     114                byte[] dummy = new byte[SigningPrivateKey.KEYSIZE_BYTES];
     115                _context.random().nextBytes(dummy);
     116                spk = new SigningPrivateKey(dummy);
     117            }
    108118            session.getProducer().createLeaseSet(session, leaseSet, li.getSigningPrivateKey(), li.getPrivateKey());
    109119            session.setLeaseSet(leaseSet);
  • core/java/src/net/i2p/client/datagram/I2PDatagramDissector.java

    r45997fd r2f7eb56  
    1515import net.i2p.crypto.DSAEngine;
    1616import net.i2p.crypto.SHA256Generator;
     17import net.i2p.crypto.SigType;
    1718import net.i2p.data.DataFormatException;
    1819import net.i2p.data.Destination;
     
    6869            // read destination
    6970            rxDest = Destination.create(dgStream);
    70             rxSign = new Signature();
     71            SigType type = rxDest.getSigningPublicKey().getType();
     72            if (type == null)
     73                throw new DataFormatException("unsupported sig type");
     74            rxSign = new Signature(type);
    7175            // read signature
    7276            rxSign.readBytes(dgStream);
  • core/java/src/net/i2p/crypto/DSAEngine.java

    r45997fd r2f7eb56  
    9090     */
    9191    public boolean verifySignature(Signature signature, byte signedData[], SigningPublicKey verifyingKey) {
     92        return verifySignature(signature, signedData, 0, signedData.length, verifyingKey);
     93    }
     94
     95    /**
     96     *  Verify using any sig type as of 0.9.12 (DSA only prior to that)
     97     */
     98    public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) {
    9299        boolean rv;
    93100        SigType type = signature.getType();
     
    96103        if (type != SigType.DSA_SHA1) {
    97104            try {
    98                 rv = altVerifySig(signature, signedData, verifyingKey);
     105                rv = altVerifySig(signature, signedData, offset, size, verifyingKey);
    99106                if ((!rv) && _log.shouldLog(Log.WARN))
    100107                    _log.warn(type + " Sig Verify Fail");
     
    108115        if (_useJavaLibs) {
    109116            try {
    110                 rv = altVerifySigSHA1(signature, signedData, verifyingKey);
     117                rv = altVerifySigSHA1(signature, signedData, offset, size, verifyingKey);
    111118                if ((!rv) && _log.shouldLog(Log.WARN))
    112119                    _log.warn("Lib DSA Sig Verify Fail");
     
    118125            }
    119126        }
    120         rv = verifySignature(signature, signedData, 0, signedData.length, verifyingKey);
     127        rv = verifySignature(signature, calculateHash(signedData, offset, size), verifyingKey);
    121128        if ((!rv) && _log.shouldLog(Log.WARN))
    122129            _log.warn("TheCrypto DSA Sig Verify Fail");
    123130        return rv;
    124     }
    125 
    126     /**
    127      *  Verify using DSA-SHA1 ONLY
    128      */
    129     public boolean verifySignature(Signature signature, byte signedData[], int offset, int size, SigningPublicKey verifyingKey) {
    130         return verifySignature(signature, calculateHash(signedData, offset, size), verifyingKey);
    131131    }
    132132
     
    257257
    258258    /**
    259      *  Sign using DSA-SHA1 or ECDSA.
     259     *  Sign using any key type.
    260260     *  Uses TheCrypto code unless configured to use the java.security libraries.
    261261     *
     
    263263     */
    264264    public Signature sign(byte data[], SigningPrivateKey signingKey) {
     265        return sign(data, 0, data.length, signingKey);
     266    }
     267
     268    /**
     269     *  Sign using any key type as of 0.9.12 (DSA-SHA1 only prior to that)
     270     *
     271     *  @return null on error
     272     */
     273    public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) {
     274        if ((signingKey == null) || (data == null) || (data.length <= 0)) return null;
    265275        SigType type = signingKey.getType();
    266276        if (type != SigType.DSA_SHA1) {
    267277            try {
    268                 return altSign(data, signingKey);
     278                return altSign(data, offset, length, signingKey);
    269279            } catch (GeneralSecurityException gse) {
    270280                if (_log.shouldLog(Log.WARN))
     
    275285        if (_useJavaLibs) {
    276286            try {
    277                 return altSignSHA1(data, signingKey);
     287                return altSignSHA1(data, offset, length, signingKey);
    278288            } catch (GeneralSecurityException gse) {
    279289                if (_log.shouldLog(Log.WARN))
     
    282292            }
    283293        }
    284         return sign(data, 0, data.length, signingKey);
    285     }
    286 
    287     /**
    288      *  Sign using DSA-SHA1 ONLY
    289      *
    290      *  @return null on error
    291      */
    292     public Signature sign(byte data[], int offset, int length, SigningPrivateKey signingKey) {
    293         if ((signingKey == null) || (data == null) || (data.length <= 0)) return null;
    294294        SHA1Hash h = calculateHash(data, offset, length);
    295295        return sign(h, signingKey);
     
    496496     *  Generic verify DSA_SHA1, ECDSA, or RSA
    497497     *  @throws GeneralSecurityException if algorithm unvailable or on other errors
    498      *  @since 0.9.9
    499      */
    500     private boolean altVerifySig(Signature signature, byte[] data, SigningPublicKey verifyingKey)
     498     *  @since 0.9.9 added off/len 0.9.12
     499     */
     500    private boolean altVerifySig(Signature signature, byte[] data, int offset, int len, SigningPublicKey verifyingKey)
    501501                        throws GeneralSecurityException {
    502502        SigType type = signature.getType();
     
    504504            throw new IllegalArgumentException("type mismatch sig=" + type + " key=" + verifyingKey.getType());
    505505        if (type == SigType.DSA_SHA1)
    506             return altVerifySigSHA1(signature, data, verifyingKey);
     506            return altVerifySigSHA1(signature, data, offset, len, verifyingKey);
    507507
    508508        java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
    509509        PublicKey pubKey = SigUtil.toJavaKey(verifyingKey);
    510510        jsig.initVerify(pubKey);
    511         jsig.update(data);
     511        jsig.update(data, offset, len);
    512512        boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
    513513        return rv;
     
    556556     *  Alternate to verifySignature() using java.security libraries.
    557557     *  @throws GeneralSecurityException if algorithm unvailable or on other errors
    558      *  @since 0.8.7
    559      */
    560     private boolean altVerifySigSHA1(Signature signature, byte[] data, SigningPublicKey verifyingKey) throws GeneralSecurityException {
     558     *  @since 0.8.7 added off/len 0.9.12
     559     */
     560    private boolean altVerifySigSHA1(Signature signature, byte[] data, int offset,
     561                                     int len, SigningPublicKey verifyingKey) throws GeneralSecurityException {
    561562        java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
    562563        PublicKey pubKey = SigUtil.toJavaDSAKey(verifyingKey);
    563564        jsig.initVerify(pubKey);
    564         jsig.update(data);
     565        jsig.update(data, offset, len);
    565566        boolean rv = jsig.verify(SigUtil.toJavaSig(signature));
    566567        //if (!rv) {
     
    574575     *  Generic sign DSA_SHA1, ECDSA, or RSA
    575576     *  @throws GeneralSecurityException if algorithm unvailable or on other errors
    576      *  @since 0.9.9
    577      */
    578     private Signature altSign(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException {
     577     *  @since 0.9.9 added off/len 0.9.12
     578     */
     579    private Signature altSign(byte[] data, int offset, int len,
     580                              SigningPrivateKey privateKey) throws GeneralSecurityException {
    579581        SigType type = privateKey.getType();
    580582        if (type == SigType.DSA_SHA1)
    581             return altSignSHA1(data, privateKey);
     583            return altSignSHA1(data, offset, len, privateKey);
    582584
    583585        java.security.Signature jsig = java.security.Signature.getInstance(type.getAlgorithmName());
    584586        PrivateKey privKey = SigUtil.toJavaKey(privateKey);
    585587        jsig.initSign(privKey, _context.random());
    586         jsig.update(data);
     588        jsig.update(data, offset, len);
    587589        return SigUtil.fromJavaSig(jsig.sign(), type);
    588590    }
     
    623625     *  Alternate to sign() using java.security libraries.
    624626     *  @throws GeneralSecurityException if algorithm unvailable or on other errors
    625      *  @since 0.8.7
    626      */
    627     private Signature altSignSHA1(byte[] data, SigningPrivateKey privateKey) throws GeneralSecurityException {
     627     *  @since 0.8.7 added off/len args 0.9.12
     628     */
     629    private Signature altSignSHA1(byte[] data, int offset, int len,
     630                                  SigningPrivateKey privateKey) throws GeneralSecurityException {
    628631        java.security.Signature jsig = java.security.Signature.getInstance("SHA1withDSA");
    629632        PrivateKey privKey = SigUtil.toJavaDSAKey(privateKey);
    630633        jsig.initSign(privKey, _context.random());
    631         jsig.update(data);
     634        jsig.update(data, offset, len);
    632635        return SigUtil.fromJavaSig(jsig.sign(), SigType.DSA_SHA1);
    633636    }
  • core/java/src/net/i2p/crypto/SU3File.java

    r45997fd r2f7eb56  
    536536     *  @since 0.9.9
    537537     */
    538     private static SigType parseSigType(String stype) {
    539         try {
    540             return SigType.valueOf(stype.toUpperCase(Locale.US));
    541         } catch (IllegalArgumentException iae) {
    542             try {
    543                 int code = Integer.parseInt(stype);
    544                 return SigType.getByCode(code);
    545             } catch (NumberFormatException nfe) {
    546                 return null;
    547              }
    548         }
    549     }
    550     /**
    551      *  @param stype number or name
    552      *  @return null if not found
    553      *  @since 0.9.9
    554      */
    555538    private static ContentType parseContentType(String ctype) {
    556539        try {
     
    640623    private static final boolean signCLI(String stype, String ctype, String inputFile, String signedFile,
    641624                                         String privateKeyFile, String version, String signerName, String keypw) {
    642         SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : parseSigType(stype);
     625        SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : SigType.parseSigType(stype);
    643626        if (type == null) {
    644627            System.out.println("Signature type " + stype + " is not supported");
     
    732715     */
    733716    private static final boolean genKeysCLI(String stype, String publicKeyFile, String privateKeyFile, String alias) {
    734         SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : parseSigType(stype);
     717        SigType type = stype == null ? SigType.getByCode(Integer.valueOf(DEFAULT_SIG_CODE)) : SigType.parseSigType(stype);
    735718        if (type == null) {
    736719            System.out.println("Signature type " + stype + " is not supported");
  • core/java/src/net/i2p/crypto/SigType.java

    r45997fd r2f7eb56  
    66import java.security.spec.InvalidParameterSpecException;
    77import java.util.HashMap;
     8import java.util.Locale;
    89import java.util.Map;
    910
     
    171172        return BY_CODE.get(Integer.valueOf(code));
    172173    }
     174
     175    /**
     176     *  Convenience for user apps
     177     *
     178     *  @param stype number or name
     179     *  @return null if not found
     180     *  @since 0.9.9 moved from SU3File in 0.9.12
     181     */
     182    public static SigType parseSigType(String stype) {
     183        try {
     184            return valueOf(stype.toUpperCase(Locale.US));
     185        } catch (IllegalArgumentException iae) {
     186            try {
     187                int code = Integer.parseInt(stype);
     188                return getByCode(code);
     189            } catch (NumberFormatException nfe) {
     190                return null;
     191             }
     192        }
     193    }
    173194}
  • core/java/src/net/i2p/data/Certificate.java

    r45997fd r2f7eb56  
    4343    /** Contains multiple certs */
    4444    public final static int CERTIFICATE_TYPE_MULTIPLE = 4;
     45    /** @since 0.9.12 */
     46    public final static int CERTIFICATE_TYPE_KEY = 5;
    4547
    4648    /**
     
    5961        byte[] payload = new byte[length];
    6062        System.arraycopy(data, off + 3, payload, 0, length);
     63        if (type == CERTIFICATE_TYPE_KEY) {
     64            try {
     65                return new KeyCertificate(payload);
     66            } catch (DataFormatException dfe) {
     67                throw new IllegalArgumentException(dfe);
     68            }
     69        }
    6170        return new Certificate(type, payload);
    6271    }
     
    7887        if (read != length)
    7988            throw new DataFormatException("Not enough bytes for the payload (read: " + read + " length: " + length + ')');
     89        if (type == CERTIFICATE_TYPE_KEY)
     90            return new KeyCertificate(payload);
    8091        return new Certificate(type, payload);
    8192    }
     
    8495    }
    8596
     97    /**
     98     *  @throws IllegalArgumentException if type < 0
     99     */
    86100    public Certificate(int type, byte[] payload) {
     101        if (type < 0)
     102            throw new IllegalArgumentException();
    87103        _type = type;
    88104        _payload = payload;
     
    94110    }
    95111
     112    /**
     113     *  @throws IllegalArgumentException if type < 0
     114     *  @throws IllegalStateException if already set
     115     */
    96116    public void setCertificateType(int type) {
     117        if (type < 0)
     118            throw new IllegalArgumentException();
     119        if (_type != 0 && _type != type)
     120            throw new IllegalStateException("already set");
    97121        _type = type;
    98122    }
     
    102126    }
    103127
     128    /**
     129     *  @throws IllegalStateException if already set
     130     */
    104131    public void setPayload(byte[] payload) {
     132        if (_payload != null)
     133            throw new IllegalStateException("already set");
    105134        _payload = payload;
    106135    }
    107136   
     137    /**
     138     *  @throws IllegalStateException if already set
     139     */
    108140    public void readBytes(InputStream in) throws DataFormatException, IOException {
     141        if (_type != 0 || _payload != null)
     142            throw new IllegalStateException("already set");
    109143        _type = (int) DataHelper.readLong(in, 1);
    110144        int length = (int) DataHelper.readLong(in, 2);
     
    150184    }
    151185   
     186    /**
     187     *  @throws IllegalStateException if already set
     188     */
    152189    public int readBytes(byte source[], int offset) throws DataFormatException {
     190        if (_type != 0 || _payload != null)
     191            throw new IllegalStateException("already set");
    153192        if (source == null) throw new DataFormatException("Cert is null");
    154193        if (source.length < offset + 3)
     
    176215    }
    177216   
     217    /**
     218     *  Up-convert this to a KeyCertificate
     219     *
     220     *  @throws DataFormatException if cert type != CERTIFICATE_TYPE_KEY
     221     *  @since 0.9.12
     222     */
     223    public KeyCertificate toKeyCertificate() throws DataFormatException {
     224        if (_type != CERTIFICATE_TYPE_KEY)
     225            throw new DataFormatException("type");
     226        return new KeyCertificate(this);
     227    }
     228
    178229    @Override
    179230    public boolean equals(Object object) {
     
    195246        if (getCertificateType() == CERTIFICATE_TYPE_NULL)
    196247            buf.append("Null certificate");
     248        else if (getCertificateType() == CERTIFICATE_TYPE_KEY)
     249            buf.append("Key certificate");
    197250        else if (getCertificateType() == CERTIFICATE_TYPE_HASHCASH)
    198251            buf.append("Hashcash certificate");
  • core/java/src/net/i2p/data/Destination.java

    r45997fd r2f7eb56  
    5858        SigningPublicKey sk = SigningPublicKey.create(in);
    5959        Certificate c = Certificate.create(in);
     60        byte[] padding;
     61        if (c.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
     62            // convert SPK to new SPK and padding
     63            KeyCertificate kcert = c.toKeyCertificate();
     64            padding = sk.getPadding(kcert);
     65            sk = sk.toTypedKey(kcert);
     66            c = kcert;
     67        } else {
     68            padding = null;
     69        }
    6070        Destination rv;
    6171        synchronized(_cache) {
     
    6878            //if (STATS)
    6979            //    I2PAppContext.getGlobalContext().statManager().addRateData("DestCache", 0);
    70             rv = new Destination(pk, sk, c);
     80            rv = new Destination(pk, sk, c, padding);
    7181            _cache.put(sk, rv);
    7282        }
     
    8797     * @since 0.9.9
    8898     */
    89     private Destination(PublicKey pk, SigningPublicKey sk, Certificate c) {
     99    private Destination(PublicKey pk, SigningPublicKey sk, Certificate c, byte[] padding) {
    90100        _publicKey = pk;
    91101        _signingKey = sk;
    92102        _certificate = c;
     103        _padding = padding;
    93104    }
    94105
     
    101112        System.arraycopy(_publicKey.getData(), 0, target, cur, PublicKey.KEYSIZE_BYTES);
    102113        cur += PublicKey.KEYSIZE_BYTES;
    103         System.arraycopy(_signingKey.getData(), 0, target, cur, SigningPublicKey.KEYSIZE_BYTES);
    104         cur += SigningPublicKey.KEYSIZE_BYTES;
     114        if (_padding != null) {
     115            System.arraycopy(_padding, 0, target, cur, _padding.length);
     116            cur += _padding.length;
     117        }
     118        System.arraycopy(_signingKey.getData(), 0, target, cur, _signingKey.length());
     119        cur += _signingKey.length();
    105120        cur += _certificate.writeBytes(target, cur);
    106121        return cur - offset;
     
    108123   
    109124    /**
    110      * @deprecated was used only by Packet.java in streaming, now unused
     125     * deprecated was used only by Packet.java in streaming, now unused
     126     * Warning - used by i2p-bote. Does NOT support alternate key types. DSA-SHA1 only.
    111127     *
    112128     * @throws IllegalStateException if data already set
     
    133149
    134150    public int size() {
    135         return PublicKey.KEYSIZE_BYTES + SigningPublicKey.KEYSIZE_BYTES + _certificate.size();
     151        int rv = PublicKey.KEYSIZE_BYTES + _signingKey.length();
     152        if (_certificate.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
     153            // cert data included in keys
     154            rv += 7;
     155            if (_padding != null)
     156                rv += _padding.length;
     157        } else {
     158            rv += _certificate.size();
     159        }
     160        return rv;
    136161    }
    137162
  • core/java/src/net/i2p/data/KeysAndCert.java

    r45997fd r2f7eb56  
    3636    protected Certificate _certificate;
    3737    protected Hash __calculatedHash;
     38    protected byte[] _padding;
    3839
    3940    public Certificate getCertificate() {
     
    8081   
    8182    /**
     83     * @throws IllegalStateException if was already set
     84     * @since 0.9.12
     85     */
     86    public void setPadding(byte[] padding) {
     87        if (_padding != null)
     88            throw new IllegalStateException();
     89        _padding = padding;
     90        __calculatedHash = null;
     91    }
     92   
     93    /**
    8294     * @throws IllegalStateException if data already set
    8395     */
     
    8698            throw new IllegalStateException();
    8799        _publicKey = PublicKey.create(in);
    88         _signingKey = SigningPublicKey.create(in);
    89         _certificate = Certificate.create(in);
     100        SigningPublicKey spk = SigningPublicKey.create(in);
     101        Certificate  cert = Certificate.create(in);
     102        if (cert.getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY) {
     103            // convert SPK to new SPK and padding
     104            KeyCertificate kcert = cert.toKeyCertificate();
     105            _signingKey = spk.toTypedKey(kcert);
     106            _padding = spk.getPadding(kcert);
     107            _certificate = kcert;
     108        } else {
     109            _signingKey = spk;
     110            _certificate = cert;
     111        }
    90112        __calculatedHash = null;
    91113    }
     
    95117            throw new DataFormatException("Not enough data to format the router identity");
    96118        _publicKey.writeBytes(out);
    97         _signingKey.writeBytes(out);
     119        if (_padding != null)
     120            out.write(_padding);
     121        _signingKey.writeTruncatedBytes(out);
    98122        _certificate.writeBytes(out);
    99123    }
     
    107131               DataHelper.eq(_signingKey, ident._signingKey)
    108132               && DataHelper.eq(_publicKey, ident._publicKey)
     133               && DataHelper.eq(_padding, ident._padding)
    109134               && DataHelper.eq(_certificate, ident._certificate);
    110135    }
     
    126151        buf.append("\n\tPublicKey: ").append(_publicKey);
    127152        buf.append("\n\tSigningPublicKey: ").append(_signingKey);
     153        if (_padding != null)
     154            buf.append("\n\tPadding: ").append(_padding.length).append(" bytes");
    128155        buf.append(']');
    129156        return buf.toString();
  • core/java/src/net/i2p/data/LeaseSet.java

    r45997fd r2f7eb56  
    276276        if ((_destination == null) || (_encryptionKey == null) || (_signingKey == null))
    277277            return null;
    278         int len = PublicKey.KEYSIZE_BYTES  // dest
    279                 + SigningPublicKey.KEYSIZE_BYTES // dest
    280                 + 3 // cert minimum, could be more, only used to size the BAOS
     278        int len = _destination.size()
    281279                + PublicKey.KEYSIZE_BYTES // encryptionKey
    282                 + SigningPublicKey.KEYSIZE_BYTES // signingKey
     280                + _signingKey.length() // signingKey
    283281                + 1
    284282                + _leases.size() * 44; // leases
     
    311309        _destination = Destination.create(in);
    312310        _encryptionKey = PublicKey.create(in);
    313         _signingKey = SigningPublicKey.create(in);
     311        // revocation signing key must be same type as the destination signing key
     312        _signingKey = new SigningPublicKey(_destination.getSigningPublicKey().getType());
     313        _signingKey.readBytes(in);
    314314        int numLeases = (int) DataHelper.readLong(in, 1);
    315315        if (numLeases > MAX_LEASES)
     
    321321            addLease(lease);
    322322        }
    323         _signature = new Signature();
     323        // signature must be same type as the destination signing key
     324        _signature = new Signature(_destination.getSigningPublicKey().getType());
    324325        _signature.readBytes(in);
    325326    }
     
    346347     */
    347348    public int size() {
    348         return PublicKey.KEYSIZE_BYTES //destination.pubKey
    349              + SigningPublicKey.KEYSIZE_BYTES // destination.signPubKey
    350              + _destination.getCertificate().size() // destination.certificate, usually 3
     349        return _destination.size()
    351350             + PublicKey.KEYSIZE_BYTES // encryptionKey
    352              + SigningPublicKey.KEYSIZE_BYTES // signingKey
     351             + _signingKey.length() // signingKey
    353352             + 1 // number of leases
    354353             + _leases.size() * (Hash.HASH_LENGTH + 4 + 8);
  • core/java/src/net/i2p/data/PrivateKeyFile.java

    r45997fd r2f7eb56  
    77import java.io.FileOutputStream;
    88import java.io.IOException;
     9import java.security.GeneralSecurityException;
     10import java.util.Locale;
    911import java.util.Map;
    1012import java.util.Properties;
     
    2022import net.i2p.client.I2PSessionException;
    2123import net.i2p.crypto.DSAEngine;
     24import net.i2p.crypto.KeyGenerator;
    2225import net.i2p.crypto.SigType;
     26import net.i2p.util.RandomSource;
    2327
    2428/**
     
    139143                pkf.setSignedCert(pkf2);
    140144                System.out.println("New destination with signed cert is:");
    141                 break;
    142145
    143146              case 't':
    144                 // TODO merge with ecdsa branch
    145                 throw new UnsupportedOperationException();
     147                // KeyCert
     148                SigType type = SigType.parseSigType(args[g.getOptind()]);
     149                if (type == null)
     150                    throw new IllegalArgumentException("Signature type " + args[g.getOptind()] + " is not supported");
     151                pkf.setKeyCert(type);
     152                System.out.println("New destination with key cert is:");
     153                break;
    146154
    147155              default:
     
    152160            System.out.println(pkf);
    153161            pkf.write();
    154             verifySignature(d);
     162            verifySignature(pkf.getDestination());
    155163        } catch (Exception e) {
    156164            e.printStackTrace();
     
    264272        newdest.setPublicKey(dest.getPublicKey());
    265273        newdest.setSigningPublicKey(dest.getSigningPublicKey());
     274        newdest.setCertificate(c);
     275        dest = newdest;
     276        return c;
     277    }
     278   
     279    /**
     280     * Change cert type - caller must also call write().
     281     * Side effect - creates new Destination object.
     282     * @since 0.9.12
     283     */
     284    public Certificate setKeyCert(SigType type) {
     285        if (type == SigType.DSA_SHA1)
     286            return setCertType(Certificate.CERTIFICATE_TYPE_NULL);
     287        if (dest == null)
     288            throw new IllegalArgumentException("Dest is null");
     289        KeyCertificate c = new KeyCertificate(type);
     290        SimpleDataStructure signingKeys[];
     291        try {
     292            signingKeys = KeyGenerator.getInstance().generateSigningKeys(type);
     293        } catch (GeneralSecurityException gse) {
     294            throw new RuntimeException("keygen fail", gse);
     295        }
     296        SigningPublicKey signingPubKey = (SigningPublicKey) signingKeys[0];
     297        signingPrivKey = (SigningPrivateKey) signingKeys[1];
     298        // dests now immutable, must create new
     299        Destination newdest = new Destination();
     300        newdest.setPublicKey(dest.getPublicKey());
     301        newdest.setSigningPublicKey(signingPubKey);
     302        // fix up key certificate or padding
     303        int len = type.getPubkeyLen();
     304        if (len < 128) {
     305            byte[] pad = new byte[128 - len];
     306            RandomSource.getInstance().nextBytes(pad);
     307            newdest.setPadding(pad);
     308        } else if (len > 128) {
     309            System.arraycopy(signingPubKey.getData(), 128, c.getPayload(), KeyCertificate.HEADER_LENGTH, len - 128);
     310        }
    266311        newdest.setCertificate(c);
    267312        dest = newdest;
     
    504549    private static final int HASH_EFFORT = VerifiedDestination.MIN_HASHCASH_EFFORT;
    505550   
    506    
    507    
    508551    private final File file;
    509552    private final I2PClient client;
  • core/java/src/net/i2p/data/RouterInfo.java

    r45997fd r2f7eb56  
    555555        }
    556556        DataHelper.readProperties(din, _options);
    557         _signature = new Signature();
     557        _signature = new Signature(_identity.getSigningPublicKey().getType());
    558558        _signature.readBytes(in);
    559559
  • core/java/src/net/i2p/data/Signature.java

    r45997fd r2f7eb56  
    1414/**
    1515 * Defines the signature as defined by the I2P data structure spec.
    16  * A signature is a 40-byte array verifying the authenticity of some data
     16 * By default, a signature is a 40-byte array verifying the authenticity of some data
    1717 * using the DSA-SHA1 algorithm.
    1818 *
    1919 * The signature is the 20-byte R followed by the 20-byte S,
    2020 * both are unsigned integers.
     21 *
     22 * As of release 0.9.8, signatures of arbitrary length and type are supported.
     23 * See SigType.
    2124 *
    2225 * @author jrandom
     
    4043
    4144    /**
     45     *  Unknown type not allowed as we won't know the length to read in the data.
     46     *
     47     *  @param type non-null
    4248     *  @since 0.9.8
    4349     */
    4450    public Signature(SigType type) {
    4551        super();
     52        if (type == null)
     53            throw new IllegalArgumentException("unknown type");
    4654        _type = type;
    4755    }
     
    5260
    5361    /**
     62     *  Should we allow an unknown type here?
     63     *
     64     *  @param type non-null
    5465     *  @since 0.9.8
    5566     */
    5667    public Signature(SigType type, byte data[]) {
    5768        super();
     69        if (type == null)
     70            throw new IllegalArgumentException("unknown type");
    5871        _type = type;
    5972        setData(data);
     
    6578
    6679    /**
     80     *  @return non-null
    6781     *  @since 0.9.8
    6882     */
  • core/java/src/net/i2p/data/SigningPrivateKey.java

    r45997fd r2f7eb56  
    1515/**
    1616 * Defines the SigningPrivateKey as defined by the I2P data structure spec.
    17  * A signing private key is 20 byte Integer. The private key represents only the
     17 * A signing private key is by default a 20 byte Integer. The private key represents only the
    1818 * exponent, not the primes, which are constant and defined in the crypto spec.
    1919 * This key varies from the PrivateKey in its usage (signing, not decrypting)
     20 *
     21 * As of release 0.9.8, keys of arbitrary length and type are supported.
     22 * See SigType.
    2023 *
    2124 * @author jrandom
  • core/java/src/net/i2p/data/SigningPublicKey.java

    r45997fd r2f7eb56  
    1212import java.io.InputStream;
    1313import java.io.IOException;
     14import java.io.OutputStream;
    1415
    1516import net.i2p.crypto.SigType;
     
    1718/**
    1819 * Defines the SigningPublicKey as defined by the I2P data structure spec.
    19  * A signing public key is 128 byte Integer. The public key represents only the
     20 * A signing public key is by default 128 byte Integer. The public key represents only the
    2021 * exponent, not the primes, which are constant and defined in the crypto spec.
    2122 * This key varies from the PrivateKey in its usage (verifying signatures, not encrypting)
     23 *
     24 * As of release 0.9.8, keys of arbitrary length and type are supported.
     25 * See SigType.
    2226 *
    2327 * @author jrandom
     
    5660
    5761    /**
     62     *  @param type if null, type is unknown
    5863     *  @since 0.9.8
    5964     */
     
    6873
    6974    /**
     75     *  @param type if null, type is unknown
    7076     *  @since 0.9.8
    7177     */
     
    7379        super();
    7480        _type = type;
    75         setData(data);
     81        if (type != null || data == null)
     82            setData(data);
     83        else
     84            _data = data;  // bypass length check
    7685    }
    7786
     
    8594    }
    8695
     96    /**
     97     *  @return if type unknown, the length of the data, or 128 if no data
     98     */
    8799    public int length() {
    88         return _type.getPubkeyLen();
     100        if (_type != null)
     101            return _type.getPubkeyLen();
     102        if (_data != null)
     103            return _data.length;
     104        return KEYSIZE_BYTES;
    89105    }
    90106
    91107    /**
     108     *  @return null if unknown
    92109     *  @since 0.9.8
    93110     */
    94111    public SigType getType() {
    95112        return _type;
     113    }
     114
     115    /**
     116     *  Up-convert this from an untyped (type 0) SPK to a typed SPK based on the Key Cert given
     117     *
     118     *  @throws IllegalArgumentException if this is already typed to a different type
     119     *  @since 0.9.12
     120     */
     121    public SigningPublicKey toTypedKey(KeyCertificate kcert) {
     122        if (_data == null)
     123            throw new IllegalStateException();
     124        SigType newType = kcert.getSigType();
     125        if (_type == newType)
     126            return this;
     127        if (_type != SigType.DSA_SHA1)
     128            throw new IllegalArgumentException("Cannot convert " + _type + " to " + newType);
     129        int newLen = newType.getPubkeyLen();
     130        if (newLen == SigType.DSA_SHA1.getPubkeyLen())
     131            return new SigningPublicKey(newType, _data);
     132        byte[] newData = new byte[newLen];
     133        if (newLen < SigType.DSA_SHA1.getPubkeyLen()) {
     134            // right-justified
     135            System.arraycopy(_data, _data.length - newLen, newData, 0, newLen);
     136        } else {
     137            // full 128 bytes + fragment in kcert
     138            System.arraycopy(_data, 0, newData, 0, _data.length);
     139            System.arraycopy(kcert.getPayload(), KeyCertificate.HEADER_LENGTH, newData, _data.length, newLen - _data.length);
     140        }
     141        return new SigningPublicKey(newType, newData);
     142    }
     143
     144    /**
     145     *  Get the portion of this (type 0) SPK that is really padding based on the Key Cert type given,
     146     *  if any
     147     *
     148     *  @return leading padding length > 0 or null
     149     *  @throws IllegalArgumentException if this is already typed to a different type
     150     *  @since 0.9.12
     151     */
     152    public byte[] getPadding(KeyCertificate kcert) {
     153        if (_data == null)
     154            throw new IllegalStateException();
     155        SigType newType = kcert.getSigType();
     156        if (_type == newType)
     157            return null;
     158        if (_type != SigType.DSA_SHA1)
     159            throw new IllegalStateException("Cannot convert " + _type + " to " + newType);
     160        int newLen = newType.getPubkeyLen();
     161        if (newLen >= SigType.DSA_SHA1.getPubkeyLen())
     162            return null;
     163        int padLen = SigType.DSA_SHA1.getPubkeyLen() - newLen;
     164        byte[] pad = new byte[padLen];
     165        System.arraycopy(_data, 0, pad, 0, padLen);
     166        return pad;
     167    }
     168   
     169    /**
     170     *  Write the data up to a max of 128 bytes.
     171     *  If longer, the rest will be written in the KeyCertificate.
     172     *  @since 0.9.12
     173     */
     174    public void writeTruncatedBytes(OutputStream out) throws DataFormatException, IOException {
     175        if (_type.getPubkeyLen() <= KEYSIZE_BYTES)
     176            out.write(_data);
     177        else
     178            out.write(_data, 0, KEYSIZE_BYTES);
    96179    }
    97180
  • core/java/src/net/i2p/data/i2cp/CreateLeaseSetMessage.java

    r45997fd r2f7eb56  
    7272            _sessionId = new SessionId();
    7373            _sessionId.readBytes(in);
     74            // Revocation is unimplemented.
     75            // As the SPK comes before the LeaseSet, we don't know the key type.
     76            // We could have some sort of callback or state setting so we get the
     77            // expected type from the session. But for now, we just assume it's 20 bytes.
     78            // Clients outside router context should throw in a dummy 20 bytes.
    7479            _signingPrivateKey = new SigningPrivateKey();
    7580            _signingPrivateKey.readBytes(in);
     
    8893            throw new I2CPMessageException("Unable to write out the message as there is not enough data");
    8994        int size = 4 // sessionId
    90                  + SigningPrivateKey.KEYSIZE_BYTES
     95                 + _signingPrivateKey.length()
    9196                 + PrivateKey.KEYSIZE_BYTES
    9297                 + _leaseSet.size();
  • core/java/src/net/i2p/data/i2cp/SessionConfig.java

    r45997fd r2f7eb56  
    191191        _options = DataHelper.readProperties(rawConfig);
    192192        _creationDate = DataHelper.readDate(rawConfig);
    193         _signature = new Signature();
     193        _signature = new Signature(_destination.getSigningPublicKey().getType());
    194194        _signature.readBytes(rawConfig);
    195195    }
  • router/java/src/net/i2p/router/networkdb/kademlia/StoreJob.java

    r45997fd r2f7eb56  
    1313import java.util.Set;
    1414
     15import net.i2p.data.Certificate;
    1516import net.i2p.data.DatabaseEntry;
    1617import net.i2p.data.Hash;
     18import net.i2p.data.LeaseSet;
    1719import net.i2p.data.RouterInfo;
    1820import net.i2p.data.TunnelId;
     
    164166                        _log.info(getJobId() + ": Error selecting closest hash that wasnt a router! " + peer + " : " + ds);
    165167                    _state.addSkipped(peer);
     168                } else if (_state.getData().getType() == DatabaseEntry.KEY_TYPE_LEASESET &&
     169                           ((LeaseSet)_state.getData()).getDestination().getCertificate().getCertificateType() == Certificate.CERTIFICATE_TYPE_KEY &&
     170                           !supportsKeyCerts((RouterInfo)ds)) {
     171                    if (_log.shouldLog(Log.INFO))
     172                        _log.info(getJobId() + ": Skipping router that doesn't support key certs " + peer + " : " + ds);
     173                    _state.addSkipped(peer);
     174                } else if (_state.getData().getType() == DatabaseEntry.KEY_TYPE_LEASESET &&
     175                           ((LeaseSet)_state.getData()).getLeaseCount() > 6 &&
     176                           !supportsBigLeaseSets((RouterInfo)ds)) {
     177                    if (_log.shouldLog(Log.INFO))
     178                        _log.info(getJobId() + ": Skipping router that doesn't support big leasesets " + peer + " : " + ds);
     179                    _state.addSkipped(peer);
    166180                } else {
    167181                    int peerTimeout = _facade.getPeerTimeout(peer);
     
    488502    }
    489503
     504    private static final String MIN_KEYCERT_VERSION = "0.9.12";
     505
     506    /**
     507     * Does he support key certs (assumed with a non-DSA key)?
     508     * @since 0.9.12
     509     */
     510    private static boolean supportsKeyCerts(RouterInfo ri) {
     511        String v = ri.getOption("router.version");
     512        if (v == null)
     513            return false;
     514        return VersionComparator.comp(v, MIN_KEYCERT_VERSION) >= 0;
     515    }
     516
     517    private static final String MIN_BIGLEASESET_VERSION = "0.9";
     518
     519    /**
     520     * Does he support more than 6 leasesets?
     521     * @since 0.9.12
     522     */
     523    private static boolean supportsBigLeaseSets(RouterInfo ri) {
     524        String v = ri.getOption("router.version");
     525        if (v == null)
     526            return false;
     527        return VersionComparator.comp(v, MIN_BIGLEASESET_VERSION) >= 0;
     528    }
     529
    490530    /**
    491531     * Called after sending a dbStore to a peer successfully,
Note: See TracChangeset for help on using the changeset viewer.