Changeset c555bb6c for core


Ignore:
Timestamp:
Jan 30, 2019 7:33:15 PM (16 months ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
4eb9368
Parents:
1bb57c4
Message:

i2cp.leaseSetEncType param:
Support comma-separated values,
check param in session config,
support stored EncTypes? in private keys.
Show types and multiple keys on LS debug page

Location:
core/java/src/net/i2p
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/i2p/client/impl/RequestLeaseSetMessageHandler.java

    r1bb57c4 rc555bb6c  
    1212import java.io.EOFException;
    1313import java.security.GeneralSecurityException;
     14import java.util.ArrayList;
     15import java.util.Collections;
     16import java.util.Comparator;
     17import java.util.List;
    1418import java.util.Map;
    1519import java.util.Properties;
     
    9195        String s = session.getOptions().getProperty(PROP_LS_ENCTYPE);
    9296        if (s != null) {
    93             EncType type = EncType.parseEncType(s);
    94             if (type != null && type != EncType.ELGAMAL_2048 && type.isAvailable())
     97            if (!s.equals("0") && !s.equals("ELGAMAL_2048"))
    9598                return true;
    9699        }
     
    151154            leaseSet.addLease(lease);
    152155        }
    153         signLeaseSet(leaseSet, session);
     156        signLeaseSet(leaseSet, isLS2, session);
    154157    }
    155158
     
    158161     *  @since 0.9.7
    159162     */
    160     protected synchronized void signLeaseSet(LeaseSet leaseSet, I2PSessionImpl session) {
     163    protected synchronized void signLeaseSet(LeaseSet leaseSet, boolean isLS2, I2PSessionImpl session) {
    161164        Destination dest = session.getMyDestination();
    162165        // also, if this session is connected to multiple routers, include other leases here
     
    166169        LeaseInfo li = _existingLeaseSets.get(dest);
    167170        if (li == null) {
    168             // [enctype:]b64 of private key
     171            // [enctype:]b64,... of private keys
    169172            String spk = session.getOptions().getProperty(PROP_LS_PK);
    170173            // [sigtype:]b64 of private key
    171174            String sspk = session.getOptions().getProperty(PROP_LS_SPK);
    172             PrivateKey privKey = null;
     175            List<PrivateKey> privKeys = new ArrayList<PrivateKey>(2);
    173176            SigningPrivateKey signingPrivKey = null;
    174177            if (spk != null && sspk != null) {
     
    184187                        useOldKeys = false;
    185188                }
    186                 colon = spk.indexOf(':');
    187                 // just ignore for now, no other types supported
    188                 if (colon >= 0)
    189                     spk = spk.substring(colon + 1);
    190189                if (useOldKeys) {
    191190                    try {
    192191                        signingPrivKey = new SigningPrivateKey(type);
    193192                        signingPrivKey.fromBase64(sspk);
    194                     } catch (DataFormatException iae) {
     193                    } catch (DataFormatException dfe) {
    195194                        useOldKeys = false;
    196195                        signingPrivKey = null;
     
    198197                }
    199198                if (useOldKeys) {
    200                     try {
    201                         privKey = new PrivateKey();
    202                         privKey.fromBase64(spk);
    203                     } catch (DataFormatException iae) {
    204                         privKey = null;
    205                     }
    206                 }
    207             }
    208             if (privKey == null && !_existingLeaseSets.isEmpty()) {
    209                 // look for keypair from another dest using same pubkey
     199                    parsePrivateKeys(spk, privKeys);
     200                }
     201            }
     202            if (privKeys.isEmpty() && !_existingLeaseSets.isEmpty()) {
     203                // look for private keys from another dest using same pubkey
    210204                PublicKey pk = dest.getPublicKey();
    211205                for (Map.Entry<Destination, LeaseInfo> e : _existingLeaseSets.entrySet()) {
    212206                    if (pk.equals(e.getKey().getPublicKey())) {
    213                         privKey = e.getValue().getPrivateKey();
     207                        privKeys.addAll(e.getValue().getPrivateKeys());
    214208                        if (_log.shouldLog(Log.DEBUG))
    215209                            _log.debug("Creating new leaseInfo keys for " + dest + " with private key from " + e.getKey());
     
    218212                }
    219213            }
    220             if (privKey != null) {
     214            if (!privKeys.isEmpty()) {
    221215                if (signingPrivKey != null) {
    222                     li = new LeaseInfo(privKey, signingPrivKey);
     216                    li = new LeaseInfo(privKeys, signingPrivKey);
    223217                    if (_log.shouldLog(Log.DEBUG))
    224218                        _log.debug("Creating new leaseInfo keys for " + dest + " WITH configured private keys");
    225219                } else {
    226                     li = new LeaseInfo(privKey, dest);
     220                    li = new LeaseInfo(privKeys, dest);
    227221                }
    228222            } else {
    229                 EncType type = EncType.ELGAMAL_2048;
     223                List<EncType> types = new ArrayList<EncType>(2);
    230224                String senc = session.getOptions().getProperty(PROP_LS_ENCTYPE);
    231225                if (senc != null) {
    232                     EncType newtype = EncType.parseEncType(senc);
    233                     if (newtype != null) {
    234                         if (newtype.isAvailable()) {
    235                             type = newtype;
    236                             if (_log.shouldDebug())
    237                                 _log.debug("Using crypto type: " + type);
     226                    String[] senca = DataHelper.split(senc, ",");
     227                    for (String sencaa : senca) {
     228                        EncType newtype = EncType.parseEncType(sencaa);
     229                        if (newtype != null) {
     230                            if (types.contains(newtype)) {
     231                                _log.error("Duplicate crypto type: " + newtype);
     232                                continue;
     233                            }
     234                            if (newtype.isAvailable()) {
     235                                types.add(newtype);
     236                                if (_log.shouldDebug())
     237                                    _log.debug("Using crypto type: " + newtype);
     238                            } else {
     239                                _log.error("Unsupported crypto type: " + newtype);
     240                            }
    238241                        } else {
    239                             _log.error("Unsupported crypto.encType: " + newtype);
     242                            _log.error("Unsupported crypto type: " + sencaa);
    240243                        }
    241                     } else {
    242                         _log.error("Bad crypto.encType: " + senc);
    243244                    }
    244                 } else {
     245                }
     246                if (types.isEmpty()) {
    245247                    if (_log.shouldDebug())
    246248                        _log.debug("Using default crypto type");
    247                 }
    248                 li = new LeaseInfo(dest, type);
     249                    types.add(EncType.ELGAMAL_2048);
     250                }
     251                li = new LeaseInfo(dest, types);
    249252                if (_log.shouldLog(Log.DEBUG))
    250253                    _log.debug("Creating new leaseInfo keys for " + dest + " without configured private keys");
     
    257260        }
    258261
    259         if (_ls2Type != DatabaseEntry.KEY_TYPE_META_LS2)
     262        if (isLS2) {
     263            LeaseSet2 ls2 = (LeaseSet2) leaseSet;
     264            if (_ls2Type != DatabaseEntry.KEY_TYPE_META_LS2) {
     265                for (PublicKey key : li.getPublicKeys()) {
     266                    ls2.addEncryptionKey(key);
     267                }
     268            }
     269        } else {
    260270            leaseSet.setEncryptionKey(li.getPublicKey());
     271        }
    261272        leaseSet.setSigningKey(li.getSigningPublicKey());
    262273        // SubSession options aren't updated via the gui, so use the primary options
     
    326337    }
    327338
     339    /**
     340     *  @param spk non-null [type:]b64[,[type:]b64]...
     341     *  @param privKeys out parameter
     342     *  @since 0.9.39
     343     */
     344    private void parsePrivateKeys(String spkl, List<PrivateKey> privKeys) {
     345        String[] spks = DataHelper.split(spkl, ",");
     346        for (String spk : spks) {
     347            int colon = spk.indexOf(':');
     348            if (colon > 0) {
     349                EncType type = EncType.parseEncType(spk.substring(0, colon));
     350                if (type != null) {
     351                    if (type.isAvailable()) {
     352                        try {
     353                            PrivateKey privKey = new PrivateKey(type);
     354                            privKey.fromBase64(spk.substring(colon + 1));
     355                            privKeys.add(privKey);
     356                            if (_log.shouldDebug())
     357                                _log.debug("Using crypto type: " + type);
     358                        } catch (DataFormatException dfe) {
     359                            _log.error("Bad private key: " + spk, dfe);
     360                        }
     361                    } else {
     362                        _log.error("Unsupported crypto type: " + type);
     363                    }
     364                } else {
     365                    _log.error("Unsupported crypto type: " + spk);
     366                }
     367            } else if (colon < 0) {
     368                try {
     369                    PrivateKey privKey = new PrivateKey();
     370                    privKey.fromBase64(spk);
     371                    privKeys.add(privKey);
     372                } catch (DataFormatException dfe) {
     373                    _log.error("Bad private key: " + spk, dfe);
     374                }
     375            } else {
     376                _log.error("Empty crypto type");
     377            }
     378        }
     379    }
     380
     381    /**
     382     *  Multiple encryption keys supported, as of 0.9.39, for LS2
     383     */
    328384    private static class LeaseInfo {
    329         private final PublicKey _pubKey;
    330         private final PrivateKey _privKey;
     385        private final List<PublicKey> _pubKeys;
     386        private final List<PrivateKey> _privKeys;
    331387        private final SigningPublicKey _signingPubKey;
    332388        private final SigningPrivateKey _signingPrivKey;
     
    334390        /**
    335391         *  New keys
     392         *  @param types must be available
    336393         */
    337         public LeaseInfo(Destination dest, EncType type) {
    338             KeyPair encKeys = KeyGenerator.getInstance().generatePKIKeys(type);
     394        public LeaseInfo(Destination dest, List<EncType> types) {
     395            if (types.size() > 1) {
     396                Collections.sort(types, Collections.reverseOrder());
     397            }
     398            _privKeys = new ArrayList<PrivateKey>(types.size());
     399            _pubKeys = new ArrayList<PublicKey>(types.size());
     400            for (EncType type : types) {
     401                KeyPair encKeys = KeyGenerator.getInstance().generatePKIKeys(type);
     402                _pubKeys.add(encKeys.getPublic());
     403                _privKeys.add(encKeys.getPrivate());
     404            }
    339405            // must be same type as the Destination's signing key
    340406            SimpleDataStructure signKeys[];
     
    344410                throw new IllegalStateException(gse);
    345411            }
    346             _pubKey = encKeys.getPublic();
    347             _privKey = encKeys.getPrivate();
    348412            _signingPubKey = (SigningPublicKey) signKeys[0];
    349413            _signingPrivKey = (SigningPrivateKey) signKeys[1];
     
    352416        /**
    353417         *  Existing keys
     418         *  @param privKeys all EncTypes must be available
    354419         *  @since 0.9.18
    355420         */
    356         public LeaseInfo(PrivateKey privKey, SigningPrivateKey signingPrivKey) {
    357             _pubKey = KeyGenerator.getPublicKey(privKey);
    358             _privKey = privKey;
     421        public LeaseInfo(List<PrivateKey> privKeys, SigningPrivateKey signingPrivKey) {
     422            if (privKeys.size() > 1) {
     423                Collections.sort(privKeys, new PrivKeyComparator());
     424            }
     425            _privKeys = privKeys;
     426            _pubKeys = new ArrayList<PublicKey>(privKeys.size());
     427            for (PrivateKey privKey : privKeys) {
     428                _pubKeys.add(KeyGenerator.getPublicKey(privKey));
     429            }
    359430            _signingPubKey = KeyGenerator.getSigningPublicKey(signingPrivKey);
    360431            _signingPrivKey = signingPrivKey;
     
    362433
    363434        /**
    364          *  Existing crypto key, new signing key
     435         *  Existing crypto keys, new signing key
     436         *  @param privKeys all EncTypes must be available
    365437         *  @since 0.9.21
    366438         */
    367         public LeaseInfo(PrivateKey privKey, Destination dest) {
     439        public LeaseInfo(List<PrivateKey> privKeys, Destination dest) {
    368440            SimpleDataStructure signKeys[];
    369441            try {
     
    372444                throw new IllegalStateException(gse);
    373445            }
    374             _pubKey = KeyGenerator.getPublicKey(privKey);
    375             _privKey = privKey;
     446            _privKeys = privKeys;
     447            _pubKeys = new ArrayList<PublicKey>(privKeys.size());
     448            for (PrivateKey privKey : privKeys) {
     449                _pubKeys.add(KeyGenerator.getPublicKey(privKey));
     450            }
    376451            _signingPubKey = (SigningPublicKey) signKeys[0];
    377452            _signingPrivKey = (SigningPrivateKey) signKeys[1];
    378453        }
    379454
     455        /** @return the first one if more than one */
    380456        public PublicKey getPublicKey() {
    381             return _pubKey;
    382         }
    383 
     457            return _pubKeys.get(0);
     458        }
     459
     460        /** @return the first one if more than one */
    384461        public PrivateKey getPrivateKey() {
    385             return _privKey;
     462            return _privKeys.get(0);
     463        }
     464
     465        /** @since 0.9.39 */
     466        public List<PublicKey> getPublicKeys() {
     467            return _pubKeys;
     468        }
     469
     470        /** @since 0.9.39 */
     471        public List<PrivateKey> getPrivateKeys() {
     472            return _privKeys;
    386473        }
    387474
     
    393480            return _signingPrivKey;
    394481        }
    395        
    396         @Override
    397         public int hashCode() {
    398             return DataHelper.hashCode(_pubKey) + 7 * DataHelper.hashCode(_privKey) + 7 * 7
    399                    * DataHelper.hashCode(_signingPubKey) + 7 * 7 * 7 * DataHelper.hashCode(_signingPrivKey);
    400         }
    401        
    402         @Override
    403         public boolean equals(Object obj) {
    404             if ((obj == null) || !(obj instanceof LeaseInfo)) return false;
    405             LeaseInfo li = (LeaseInfo) obj;
    406             return DataHelper.eq(_pubKey, li.getPublicKey()) && DataHelper.eq(_privKey, li.getPrivateKey())
    407                    && DataHelper.eq(_signingPubKey, li.getSigningPublicKey())
    408                    && DataHelper.eq(_signingPrivKey, li.getSigningPrivateKey());
     482
     483        /**
     484         *  Reverse order by enc type
     485         *  @since 0.9.39
     486         */
     487        private static class PrivKeyComparator implements Comparator<PrivateKey> {
     488            public int compare(PrivateKey l, PrivateKey r) {
     489                return r.getType().compareTo(l.getType());
     490            }
    409491        }
    410492    }
  • core/java/src/net/i2p/client/impl/RequestVariableLeaseSetMessageHandler.java

    r1bb57c4 rc555bb6c  
    7878            leaseSet.addLease(lease);
    7979        }
    80         signLeaseSet(leaseSet, session);
     80        signLeaseSet(leaseSet, isLS2, session);
    8181    }
    8282}
  • core/java/src/net/i2p/data/LeaseSet2.java

    r1bb57c4 rc555bb6c  
    556556        buf.append("\n\tEncryption Keys: ").append(sz);
    557557        for (int i = 0; i < sz; i++) {
    558             buf.append("\n\tEncryptionKey ").append(i).append(": ").append(keys.get(i));
     558            buf.append("\n\tEncryption Key ").append(i).append(": ").append(keys.get(i));
    559559        }
    560560        if (isOffline()) {
Note: See TracChangeset for help on using the changeset viewer.