Changeset 3089234


Ignore:
Timestamp:
Aug 24, 2014 7:15:26 PM (7 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
2b9a368
Parents:
04ad7de
Message:

PrivateKeyFile?: New constructor with padding
Router:

  • Use eepPriv.dat format for router keys file (thx orignal)
  • Consolidate router keys readin code
  • Update killKeys file list

RouterPrivateKeyFile?: New extension to add getRouterIdentity()

Files:
1 added
6 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/i2p/data/PrivateKeyFile.java

    r04ad7de r3089234  
    22
    33
     4import java.io.BufferedInputStream;
    45import java.io.ByteArrayInputStream;
    56import java.io.File;
    67import java.io.FileInputStream;
    7 import java.io.FileOutputStream;
     8import java.io.InputStream;
    89import java.io.IOException;
     10import java.io.OutputStream;
    911import java.security.GeneralSecurityException;
    1012import java.util.Locale;
     
    2527import net.i2p.crypto.SigType;
    2628import net.i2p.util.RandomSource;
     29import net.i2p.util.SecureFileOutputStream;
    2730
    2831/**
     
    4952    private static final int HASH_EFFORT = VerifiedDestination.MIN_HASHCASH_EFFORT;
    5053   
    51     private final File file;
     54    protected final File file;
    5255    private final I2PClient client;
    5356    private Destination dest;
    54     private PrivateKey privKey;
    55     private SigningPrivateKey signingPrivKey;
     57    protected PrivateKey privKey;
     58    protected SigningPrivateKey signingPrivKey;
    5659
    5760    /**
     
    225228    public PrivateKeyFile(File file, PublicKey pubkey, SigningPublicKey spubkey, Certificate cert,
    226229                          PrivateKey pk, SigningPrivateKey spk) {
     230        this(file, pubkey, spubkey, cert, pk, spk, null);
     231    }
     232   
     233    /**
     234     *  @param padding null OK, must be non-null if spubkey length < 128
     235     *  @throws IllegalArgumentException on mismatch of spubkey and spk types
     236     *  @since 0.9.16
     237     */
     238    public PrivateKeyFile(File file, PublicKey pubkey, SigningPublicKey spubkey, Certificate cert,
     239                          PrivateKey pk, SigningPrivateKey spk, byte[] padding) {
    227240        if (spubkey.getType() != spk.getType())
    228241            throw new IllegalArgumentException("Signing key type mismatch");
     
    233246        this.dest.setSigningPublicKey(spubkey);
    234247        this.dest.setCertificate(cert);
     248        if (padding != null)
     249            this.dest.setPadding(padding);
    235250        this.privKey = pk;
    236251        this.signingPrivKey = spk;
     
    242257    public Destination createIfAbsent() throws I2PException, IOException, DataFormatException {
    243258        if(!this.file.exists()) {
    244             FileOutputStream out = null;
     259            OutputStream out = null;
    245260            try {
    246                 out = new FileOutputStream(this.file);
     261                out = new SecureFileOutputStream(this.file);
    247262                if (this.client != null)
    248263                    this.client.createDestination(out);
     
    258273    }
    259274   
    260     /** Also sets the local privKey and signingPrivKey */
     275    /**
     276     *  If the destination is not set, read it in from the file.
     277     *  Also sets the local privKey and signingPrivKey.
     278     */
    261279    public Destination getDestination() throws I2PSessionException, IOException, DataFormatException {
    262280        if (dest == null) {
     
    409427
    410428    public I2PSession open(Properties opts) throws I2PSessionException, IOException {
    411         FileInputStream in = null;
    412         try {
    413             in = new FileInputStream(this.file);
     429        InputStream in = null;
     430        try {
     431            in = new BufferedInputStream(new FileInputStream(this.file));
    414432            I2PSession s = this.client.createSession(in, opts);
    415433            return s;
     
    425443     */
    426444    public void write() throws IOException, DataFormatException {
    427         FileOutputStream out = null;
    428         try {
    429             out = new FileOutputStream(this.file);
     445        OutputStream out = null;
     446        try {
     447            out = new SecureFileOutputStream(this.file);
    430448            this.dest.writeBytes(out);
    431449            this.privKey.writeBytes(out);
    432450            this.signingPrivKey.writeBytes(out);
    433             out.flush();
    434451        } finally {
    435452            if (out != null) {
  • router/java/src/net/i2p/router/KeyManager.java

    r04ad7de r3089234  
    5050    public final static String PROP_KEYDIR = "router.keyBackupDir";
    5151    public final static String DEFAULT_KEYDIR = "keyBackup";
    52     private final static String KEYFILE_PRIVATE_ENC = "privateEncryption.key";
    53     private final static String KEYFILE_PUBLIC_ENC = "publicEncryption.key";
    54     private final static String KEYFILE_PRIVATE_SIGNING = "privateSigning.key";
    55     private final static String KEYFILE_PUBLIC_SIGNING = "publicSigning.key";
     52    public final static String KEYFILE_PRIVATE_ENC = "privateEncryption.key";
     53    public final static String KEYFILE_PUBLIC_ENC = "publicEncryption.key";
     54    public final static String KEYFILE_PRIVATE_SIGNING = "privateSigning.key";
     55    public final static String KEYFILE_PUBLIC_SIGNING = "publicSigning.key";
    5656   
    5757    public KeyManager(RouterContext context) {
  • router/java/src/net/i2p/router/Router.java

    r04ad7de r3089234  
    3535import net.i2p.router.message.GarlicMessageHandler;
    3636import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
     37import net.i2p.router.startup.CreateRouterInfoJob;
    3738import net.i2p.router.startup.StartupJob;
    3839import net.i2p.router.startup.WorkingDir;
     
    680681     *
    681682     */
    682     private static final String _rebuildFiles[] = new String[] { "router.info",
    683                                                                  "router.keys",
    684                                                                  "netDb/my.info",      // no longer used
    685                                                                  "connectionTag.keys", // never used?
    686                                                                  "keyBackup/privateEncryption.key",
    687                                                                  "keyBackup/privateSigning.key",
    688                                                                  "keyBackup/publicEncryption.key",
    689                                                                  "keyBackup/publicSigning.key",
    690                                                                  "sessionKeys.dat"     // no longer used
    691                                                                };
     683    private static final String _rebuildFiles[] = new String[] {
     684        CreateRouterInfoJob.INFO_FILENAME,
     685        CreateRouterInfoJob.KEYS_FILENAME,
     686        CreateRouterInfoJob.KEYS2_FILENAME,
     687        "netDb/my.info",      // no longer used
     688        "connectionTag.keys", // never used?
     689        KeyManager.DEFAULT_KEYDIR + '/' + KeyManager.KEYFILE_PRIVATE_ENC,
     690        KeyManager.DEFAULT_KEYDIR + '/' + KeyManager.KEYFILE_PUBLIC_ENC,
     691        KeyManager.DEFAULT_KEYDIR + '/' + KeyManager.KEYFILE_PRIVATE_SIGNING,
     692        KeyManager.DEFAULT_KEYDIR + '/' + KeyManager.KEYFILE_PUBLIC_SIGNING,
     693        "sessionKeys.dat"     // no longer used
     694    };
    692695
    693696    public void killKeys() {
  • router/java/src/net/i2p/router/startup/CreateRouterInfoJob.java

    r04ad7de r3089234  
    2222import net.i2p.data.KeyCertificate;
    2323import net.i2p.data.PrivateKey;
     24import net.i2p.data.PrivateKeyFile;
    2425import net.i2p.data.PublicKey;
    2526import net.i2p.data.router.RouterIdentity;
     
    4748   
    4849    public static final String INFO_FILENAME = "router.info";
    49     static final String KEYS_FILENAME = "router.keys";
    50     static final String KEYS2_FILENAME = "router.keys2";
     50    public static final String KEYS_FILENAME = "router.keys";
     51    public static final String KEYS2_FILENAME = "router.keys.dat";
    5152    private static final String PROP_ROUTER_SIGTYPE = "router.sigType";
    5253    /** TODO when changing, check isAvailable() and fallback to DSA_SHA1 */
    5354    private static final SigType DEFAULT_SIGTYPE = SigType.DSA_SHA1;
    54     static final byte[] KEYS2_MAGIC = DataHelper.getASCII("I2Pkeys2");
    55     static final int KEYS2_UNUSED_BYTES = 28;
    5655
    5756    CreateRouterInfoJob(RouterContext ctx, Job next) {
     
    7675     *  router.keys2, and 4 individual key files under keyBackup/
    7776     *
    78      *  router.keys2 file format: Note that this is NOT the
    79      *  same "eepPriv.dat" format used by the client code.
    80      *<pre>
    81      *   - Magic "I2Pkeys2"
    82      *   - 2 byte crypto type, always 0000 for now
    83      *   - 2 byte sig type, see SigType
    84      *   - 28 bytes unused
    85      *   - Private key (256 bytes)
    86      *   - Signing Private key (20 bytes or see SigType)
    87      *   - Public key (256 bytes)
    88      *   - Random padding for Signing Public Key if less than 128 bytes
    89      *   - Signing Public key (128 bytes or see SigTpe)
    90      *  Total 660 bytes
    91      *</pre>
     77     *  router.keys2 file format: This is the
     78     *  same "eepPriv.dat" format used by the client code,
     79     *  as documented in PrivateKeyFile.
    9280     *
    9381     *  Old router.keys file format: Note that this is NOT the
     
    10795        RouterInfo info = new RouterInfo();
    10896        OutputStream fos1 = null;
    109         OutputStream fos2 = null;
    11097        try {
    11198            info.setAddresses(getContext().commSystem().createAddresses());
     
    152139            info.writeBytes(fos1);
    153140           
    154             // write router.keys2
     141            // write router.keys.dat
    155142            File kfile = new File(getContext().getRouterDir(), KEYS2_FILENAME);
    156             fos2 = new BufferedOutputStream(new SecureFileOutputStream(kfile));
    157             fos2.write(KEYS2_MAGIC);
    158             DataHelper.writeLong(fos2, 2, 0);
    159             DataHelper.writeLong(fos2, 2, type.getCode());
    160             fos2.write(new byte[KEYS2_UNUSED_BYTES]);
    161             privkey.writeBytes(fos2);
    162             signingPrivKey.writeBytes(fos2);
    163             pubkey.writeBytes(fos2);
    164             if (padding != null)
    165                 fos2.write(padding);
    166             signingPubKey.writeBytes(fos2);
     143            PrivateKeyFile pkf = new PrivateKeyFile(kfile, pubkey, signingPubKey, cert,
     144                                                    privkey, signingPrivKey, padding);
     145            pkf.write();
    167146           
    168147            getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
     
    179158        } finally {
    180159            if (fos1 != null) try { fos1.close(); } catch (IOException ioe) {}
    181             if (fos2 != null) try { fos2.close(); } catch (IOException ioe) {}
    182160        }
    183161        return info;
  • router/java/src/net/i2p/router/startup/LoadRouterInfoJob.java

    r04ad7de r3089234  
    1717
    1818import net.i2p.crypto.SigType;
     19import net.i2p.data.Certificate;
    1920import net.i2p.data.DataFormatException;
    2021import net.i2p.data.DataHelper;
    2122import net.i2p.data.PrivateKey;
    2223import net.i2p.data.PublicKey;
    23 import net.i2p.data.router.RouterInfo;
    2424import net.i2p.data.SigningPrivateKey;
    2525import net.i2p.data.SigningPublicKey;
     26import net.i2p.data.router.RouterIdentity;
     27import net.i2p.data.router.RouterInfo;
     28import net.i2p.data.router.RouterPrivateKeyFile;
    2629import net.i2p.router.JobImpl;
    2730import net.i2p.router.Router;
     
    7780       
    7881        InputStream fis1 = null;
    79         InputStream fis2 = null;
    8082        try {
    8183            // if we have a routerinfo but no keys, things go bad in a hurry:
     
    98100           
    99101            if (keys2Exist || keysExist) {
    100                 SigType stype;
    101                 if (keys2Exist) {
    102                     fis2 = new BufferedInputStream(new FileInputStream(rkf2));
    103                     // read keys2 headers
    104                     byte[] magic = new byte[CreateRouterInfoJob.KEYS2_MAGIC.length];
    105                     DataHelper.read(fis2, magic);
    106                     if (!DataHelper.eq(magic, CreateRouterInfoJob.KEYS2_MAGIC))
    107                         throw new IOException("Bad magic");
    108                     int ctype = (int) DataHelper.readLong(fis2, 2);
    109                     if (ctype != 0)
    110                         throw new IOException("Unsupported RI crypto type " + ctype);
    111                     int sstype = (int) DataHelper.readLong(fis2, 2);
    112                     stype = SigType.getByCode(sstype);
    113                     if (stype == null || !stype.isAvailable())
    114                         throw new IOException("Unsupported RI sig type " + stype);
    115                     DataHelper.skip(fis2, CreateRouterInfoJob.KEYS2_UNUSED_BYTES);
    116                 } else {
    117                     fis2 = new BufferedInputStream(new FileInputStream(rkf));
    118                     stype = SigType.DSA_SHA1;
    119                 }
     102                KeyData kd = readKeyData(rkf, rkf2);
     103                PublicKey pubkey = kd.routerIdentity.getPublicKey();
     104                SigningPublicKey signingPubKey = kd.routerIdentity.getSigningPublicKey();
     105                PrivateKey privkey = kd.privateKey;
     106                SigningPrivateKey signingPrivKey = kd.signingPrivateKey;
     107                SigType stype = signingPubKey.getType();
    120108
    121109                // check if the sigtype config changed
     
    123111                boolean sigTypeChanged = stype != cstype;
    124112
    125                 PrivateKey privkey = new PrivateKey();
    126                 privkey.readBytes(fis2);
    127113                if (sigTypeChanged || shouldRebuild(privkey)) {
    128114                    if (sigTypeChanged)
     
    134120                        fis1 = null;
    135121                    }
    136                     try { fis2.close(); } catch (IOException ioe) {}
    137                     fis2 = null;
    138122                    rif.delete();
    139123                    rkf.delete();
     
    141125                    return;
    142126                }
    143                 SigningPrivateKey signingPrivKey = new SigningPrivateKey(stype);
    144                 signingPrivKey.readBytes(fis2);
    145                 PublicKey pubkey = new PublicKey();
    146                 pubkey.readBytes(fis2);
    147                 SigningPublicKey signingPubKey = new SigningPublicKey(stype);
    148                 int padLen = SigningPublicKey.KEYSIZE_BYTES - signingPubKey.length();
    149                 if (padLen > 0) {
    150                     // we lose the padding as keymanager doesn't store it, what to do?
    151                     DataHelper.skip(fis2, padLen);
    152                 }
    153                 signingPubKey.readBytes(fis2);
    154127               
    155128                getContext().keyManager().setKeys(pubkey, privkey, signingPubKey, signingPrivKey);
     
    162135                try { fis1.close(); } catch (IOException ioe2) {}
    163136                fis1 = null;
    164             }
    165             if (fis2 != null) {
    166                 try { fis2.close(); } catch (IOException ioe2) {}
    167                 fis2 = null;
    168137            }
    169138            rif.delete();
     
    178147                fis1 = null;
    179148            }
    180             if (fis2 != null) {
    181                 try { fis2.close(); } catch (IOException ioe) {}
    182                 fis2 = null;
    183             }
    184149            rif.delete();
    185150            rkf.delete();
     
    187152        } finally {
    188153            if (fis1 != null) try { fis1.close(); } catch (IOException ioe) {}
    189             if (fis2 != null) try { fis2.close(); } catch (IOException ioe) {}
    190154        }
    191155    }
     
    220184        return uselong != haslong;
    221185    }
     186
     187    /** @since 0.9.16 */
     188    public static class KeyData {
     189        public final RouterIdentity routerIdentity;
     190        public final PrivateKey privateKey;
     191        public final SigningPrivateKey signingPrivateKey;
     192
     193        public KeyData(RouterIdentity ri, PrivateKey pk, SigningPrivateKey spk) {
     194            routerIdentity = ri;
     195            privateKey = pk;
     196            signingPrivateKey = spk;
     197        }
     198    }
     199
     200    /**
     201     *  @param rkf1 in router.keys format, tried second
     202     *  @param rkf2 in eepPriv.dat format, tried first
     203     *  @return non-null, throws IOE if neither exisits
     204     *  @since 0.9.16
     205     */
     206    public static KeyData readKeyData(File rkf1, File rkf2) throws DataFormatException, IOException {
     207        RouterIdentity ri;
     208        PrivateKey privkey;
     209        SigningPrivateKey signingPrivKey;
     210        if (rkf2.exists()) {
     211            RouterPrivateKeyFile pkf = new RouterPrivateKeyFile(rkf2);
     212            ri = pkf.getRouterIdentity();
     213            privkey = pkf.getPrivKey();
     214            signingPrivKey = pkf.getSigningPrivKey();
     215        } else {
     216            InputStream fis = null;
     217            try {
     218                fis = new BufferedInputStream(new FileInputStream(rkf1));
     219                privkey = new PrivateKey();
     220                privkey.readBytes(fis);
     221                signingPrivKey = new SigningPrivateKey();
     222                signingPrivKey.readBytes(fis);
     223                PublicKey pubkey = new PublicKey();
     224                pubkey.readBytes(fis);
     225                SigningPublicKey signingPubKey = new SigningPublicKey();
     226                signingPubKey.readBytes(fis);
     227                ri = new RouterIdentity();
     228                ri.setPublicKey(pubkey);
     229                ri.setSigningPublicKey(signingPubKey);
     230                ri.setCertificate(Certificate.NULL_CERT);
     231            } finally {
     232                if (fis != null) try { fis.close(); } catch (IOException ioe) {}
     233            }
     234        }
     235        return new KeyData(ri, privkey, signingPrivKey);
     236    }
    222237}
  • router/java/src/net/i2p/router/startup/RebuildRouterInfoJob.java

    r04ad7de r3089234  
    99 */
    1010
    11 import java.io.BufferedInputStream;
    1211import java.io.File;
    13 import java.io.FileInputStream;
    1412import java.io.FileOutputStream;
    15 import java.io.InputStream;
    1613import java.io.IOException;
    1714import java.util.Properties;
     
    3027import net.i2p.router.Router;
    3128import net.i2p.router.RouterContext;
     29import net.i2p.router.startup.LoadRouterInfoJob.KeyData;
    3230import net.i2p.util.Log;
    3331import net.i2p.util.SecureFileOutputStream;
     
    9795            RouterInfo oldinfo = getContext().router().getRouterInfo();
    9896            if (oldinfo == null) {
    99                 info = new RouterInfo();
    100                 InputStream fis = null;
    10197                try {
    102                     SigType stype;
    103                     if (keyFile2.exists()) {
    104                         fis = new BufferedInputStream(new FileInputStream(keyFile2));
    105                         byte[] magic = new byte[CreateRouterInfoJob.KEYS2_MAGIC.length];
    106                         DataHelper.read(fis, magic);
    107                         if (!DataHelper.eq(magic, CreateRouterInfoJob.KEYS2_MAGIC))
    108                             throw new IOException("Bad magic");
    109                         int ctype = (int) DataHelper.readLong(fis, 2);
    110                         if (ctype != 0)
    111                             throw new IOException("Unsupported RI crypto type " + ctype);
    112                         int sstype = (int) DataHelper.readLong(fis, 2);
    113                         stype = SigType.getByCode(sstype);
    114                         if (stype == null || !stype.isAvailable())
    115                             throw new IOException("Unsupported RI sig type " + stype);
    116                         DataHelper.skip(fis, CreateRouterInfoJob.KEYS2_UNUSED_BYTES);
    117                     } else {
    118                         fis = new BufferedInputStream(new FileInputStream(keyFile));
    119                         stype = SigType.DSA_SHA1;
    120                     }
    121                     PrivateKey privkey = new PrivateKey();
    122                     privkey.readBytes(fis);
    123                     SigningPrivateKey signingPrivKey = new SigningPrivateKey(stype);
    124                     signingPrivKey.readBytes(fis);
    125                     PublicKey pubkey = new PublicKey();
    126                     pubkey.readBytes(fis);
    127                     SigningPublicKey signingPubKey = new SigningPublicKey(stype);
    128                     byte[] padding;
    129                     int padLen = SigningPublicKey.KEYSIZE_BYTES - signingPubKey.length();
    130                     if (padLen > 0) {
    131                         padding = new byte[padLen];
    132                         DataHelper.read(fis, padding);
    133                     } else {
    134                         padding = null;
    135                     }
    136                     signingPubKey.readBytes(fis);
    137                     RouterIdentity ident = new RouterIdentity();
    138                     Certificate cert = CreateRouterInfoJob.createCertificate(getContext(), signingPubKey);
    139                     ident.setCertificate(cert);
    140                     ident.setPublicKey(pubkey);
    141                     ident.setSigningPublicKey(signingPubKey);
    142                     if (padding != null)
    143                         ident.setPadding(padding);
    144                     info.setIdentity(ident);
     98                    KeyData kd = LoadRouterInfoJob.readKeyData(keyFile, keyFile2);
     99                    info = new RouterInfo();
     100                    info.setIdentity(kd.routerIdentity);
    145101                } catch (Exception e) {
    146102                    _log.log(Log.CRIT, "Error reading in the key data from " + keyFile.getAbsolutePath(), e);
    147                     if (fis != null) try { fis.close(); } catch (IOException ioe) {}
    148                     fis = null;
    149103                    keyFile.delete();
     104                    keyFile2.delete();
    150105                    rebuildRouterInfo(alreadyRunning);
    151106                    return;
    152                 } finally {
    153                     if (fis != null) try { fis.close(); } catch (IOException ioe) {}
    154107                }
    155108            } else {
Note: See TracChangeset for help on using the changeset viewer.