Changeset eb0920e2


Ignore:
Timestamp:
Mar 29, 2019 12:50:41 PM (17 months ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
7501e3f
Parents:
ba801be
Message:

NetDB: Persistence for blinding cache

Files:
3 edited

Legend:

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

    rba801be reb0920e2  
    219219     *
    220220     *  @param b 35+ bytes
     221     *  @return BlindData structure, use getUnblindedPubKey() for the result
    221222     *  @throws IllegalArgumentException on bad inputs
    222223     *  @throws UnsupportedOperationException unless supported SigTypes
     
    314315    }
    315316
     317    public static void main(String args[]) throws Exception {
     318        if (args.length != 1) {
     319            System.out.println("Usage: blinding {56 chars}.b32.i2p");
     320            System.exit(1);
     321        }
     322        System.out.println("Blinded B32: " + args[0]);
     323        System.out.println(decode(I2PAppContext.getGlobalContext(), args[0]).toString());
     324    }
     325
    316326/******
    317327    public static void main(String args[]) throws Exception {
  • core/java/src/net/i2p/data/BlindData.java

    rba801be reb0920e2  
    4343        _blindType = blindType;
    4444        _secret = secret;
    45         _authType = 0;
     45        _authType = -1;
    4646        _authKey = null;
    4747        // defer until needed
     
    5454    public SigningPublicKey getUnblindedPubKey() {
    5555        return _clearSPK;
     56    }
     57
     58    /**
     59     *  @return The type of the blinded key
     60     */
     61    public SigType getBlindedSigType() {
     62        return _blindType;
    5663    }
    5764
     
    116123
    117124    /**
    118      *  @return 0 for no client auth
     125     *  @return -1 for no client auth
    119126     */
    120127    public int getAuthType() {
    121128        return _authType;
     129    }
     130
     131    /**
     132     *  @return null for no client auth
     133     */
     134    public PrivateKey getAuthPrivKey() {
     135        return _authKey;
    122136    }
    123137
     
    148162    public synchronized String toString() {
    149163        calculate();
    150         StringBuilder buf = new StringBuilder(256);
     164        StringBuilder buf = new StringBuilder(1024);
    151165        buf.append("[BlindData: ");
    152166        buf.append("\n\tSigningPublicKey: ").append(_clearSPK);
     
    154168        buf.append("\n\tBlindedPublicKey: ").append(_blindSPK);
    155169        buf.append("\n\tBlinded Hash    : ").append(_blindHash);
    156         buf.append("\n\tSecret: ").append(_secret);
     170        if (_secret != null)
     171            buf.append("\n\tSecret          : \"").append(_secret).append('"');
     172        buf.append("\n\tAuth Type       : ");
     173        if (_authType >= 0)
     174            buf.append(_authType);
     175        else
     176            buf.append("none");
     177        if (_authKey != null)
     178            buf.append("\n\tAuth Key   : ").append(_authKey);
    157179        if (_dest != null)
    158180            buf.append("\n\tDestination: ").append(_dest);
    159         if (_dest != null)
     181        else
    160182            buf.append("\n\tDestination: unknown");
    161183        buf.append(']');
  • router/java/src/net/i2p/router/networkdb/kademlia/BlindCache.java

    rba801be reb0920e2  
    11package net.i2p.router.networkdb.kademlia;
    22
     3import java.io.BufferedReader;
     4import java.io.BufferedWriter;
     5import java.io.File;
     6import java.io.FileInputStream;
     7import java.io.InputStreamReader;
     8import java.io.IOException;
     9import java.io.OutputStreamWriter;
     10import java.io.PrintWriter;
    311import java.util.concurrent.ConcurrentHashMap;
    412
    513import net.i2p.crypto.Blinding;
     14import net.i2p.crypto.EncType;
    615import net.i2p.crypto.SigType;
     16import net.i2p.data.Base64;
    717import net.i2p.data.BlindData;
     18import net.i2p.data.DataFormatException;
     19import net.i2p.data.DataHelper;
    820import net.i2p.data.Destination;
    921import net.i2p.data.Hash;
     22import net.i2p.data.PrivateKey;
    1023import net.i2p.data.SigningPublicKey;
    1124import net.i2p.router.RouterContext;
     25import net.i2p.util.Log;
     26import net.i2p.util.SecureFileOutputStream;
    1227
    1328/**
     
    2540    // dest hash
    2641    private final ConcurrentHashMap<Hash, BlindData> _hashCache;
     42
     43    private static final String PERSIST_FILE = "router.blindcache.dat";
    2744
    2845    /**
     
    202219     *
    203220     */
    204     public void rollover() {
     221    public synchronized void rollover() {
    205222        _reverseCache.clear();
    206223        for (BlindData bd : _cache.values()) {
     
    209226    }
    210227
    211     private void load() {
    212         // TODO
    213     }
    214 
    215     private void store() {
    216         // TODO
     228    /**
     229     *  Load from file.
     230     *  Format:
     231     *  sigtype,bsigtype,b64 pubkey,[b64 secret],[b64 dest]
     232     */
     233    private synchronized void load() {
     234        File file = new File(_context.getConfigDir(), PERSIST_FILE);
     235        if (!file.exists())
     236            return;
     237        Log log = _context.logManager().getLog(BlindCache.class);
     238        int count = 0;
     239        BufferedReader br = null;
     240        try {
     241            br = new BufferedReader(new InputStreamReader(
     242                        new FileInputStream(file), "ISO-8859-1"));
     243            String line = null;
     244            while ( (line = br.readLine()) != null) {
     245                if (line.startsWith("#"))
     246                    continue;
     247                try {
     248                    addToCache(fromPersistentString(line));
     249                    count++;
     250                } catch (IllegalArgumentException iae) {
     251                    if (log.shouldLog(Log.WARN))
     252                        log.warn("Error reading cache entry", iae);
     253                } catch (DataFormatException dfe) {
     254                    if (log.shouldLog(Log.WARN))
     255                        log.warn("Error reading cache entry", dfe);
     256                }
     257            }
     258        } catch (IOException ioe) {
     259            if (log.shouldLog(Log.WARN) && file.exists())
     260                log.warn("Error reading the blinding cache file", ioe);
     261        } finally {
     262            if (br != null) try { br.close(); } catch (IOException ioe) {}
     263        }
     264        if (log.shouldLog(Log.INFO))
     265            log.info("Loaded " + count + " entries from " + file);
     266    }
     267
     268    private synchronized void store() {
     269        if (_cache.isEmpty())
     270            return;
     271        Log log = _context.logManager().getLog(BlindCache.class);
     272        int count = 0;
     273        File file = new File(_context.getConfigDir(), PERSIST_FILE);
     274        PrintWriter out = null;
     275        try {
     276            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(file), "ISO-8859-1")));
     277            out.println("# Blinding cache entries. Format is: sigtype,bsigtype,authtype,time,key,[secret],[privkey],[dest]");
     278            for (BlindData bd : _cache.values()) {
     279                 out.println(toPersistentString(bd));
     280                 count++;
     281            }
     282            if (out.checkError())
     283                throw new IOException("Failed write to " + file);
     284        } catch (IOException ioe) {
     285            if (log.shouldLog(Log.WARN))
     286                log.warn("Error writing the blinding cache File", ioe);
     287        } finally {
     288            if (out != null) out.close();
     289        }
     290        if (log.shouldLog(Log.INFO))
     291            log.info("Stored " + count + " entries to " + file);
     292    }
     293
     294    /**
     295     *  Format:
     296     *  sigtype,bsigtype,authtype,timestamp,b64 pubkey,[b64 secret],[b64 auth privkey],[b64 dest]
     297     */
     298    private BlindData fromPersistentString(String line) throws DataFormatException {
     299        String[] ss = DataHelper.split(line, ",", 8);
     300        if (ss.length != 8)
     301            throw new DataFormatException("bad format");
     302        int ist1, ist2, auth;
     303        long time;
     304        try {
     305            ist1 = Integer.parseInt(ss[0]);
     306            ist2 = Integer.parseInt(ss[1]);
     307            auth = Integer.parseInt(ss[2]);
     308            time = Long.parseLong(ss[3]);
     309        } catch (NumberFormatException nfe) {
     310            throw new DataFormatException("bad codes", nfe);
     311        }
     312        SigType st1 = SigType.getByCode(ist1);
     313        SigType st2 = SigType.getByCode(ist2);
     314        if (st1 == null || !st1.isAvailable() || st2 == null || !st2.isAvailable())
     315            throw new DataFormatException("bad codes");
     316        SigningPublicKey spk = new SigningPublicKey(st1);
     317        spk.fromBase64(ss[4]);
     318        String secret;
     319        if (ss[5].length() > 0) {
     320            byte[] b = Base64.decode(ss[5]);
     321            if (b == null)
     322                throw new DataFormatException("bad secret");
     323            secret = DataHelper.getUTF8(b);
     324        } else {
     325            secret = null;
     326        }
     327        PrivateKey privkey;
     328        if (ss[6].length() > 0) {
     329            byte[] b = Base64.decode(ss[6]);
     330            if (b == null)
     331                throw new DataFormatException("bad privkey");
     332            privkey = new PrivateKey(EncType.ECIES_X25519, b);
     333        } else {
     334            privkey = null;
     335        }
     336        BlindData rv;
     337        // TODO pass privkey
     338        if (ss[7].length() > 0) {
     339            Destination dest = new Destination(ss[7]);
     340            if (!spk.equals(dest.getSigningPublicKey()))
     341                throw new DataFormatException("spk mismatch");
     342            rv = new BlindData(_context, dest, st2, secret);
     343        } else {
     344            rv = new BlindData(_context, spk, st2, secret);
     345        }
     346        return rv;
     347    }
     348
     349    /**
     350     *  Format:
     351     *  sigtype,bsigtype,authtype,timestamp,b64 pubkey,[b64 secret],[b64 auth privkey],[b64 dest]
     352     */
     353    private static String toPersistentString(BlindData bd) {
     354        StringBuilder buf = new StringBuilder(1024);
     355        SigningPublicKey spk = bd.getUnblindedPubKey();
     356        buf.append(spk.getType().getCode()).append(',');
     357        buf.append(bd.getBlindedSigType().getCode()).append(',');
     358        buf.append(bd.getAuthType()).append(',');
     359        // timestamp todo
     360        buf.append('0').append(',');
     361        buf.append(spk.toBase64()).append(',');
     362        String secret = bd.getSecret();
     363        if (secret != null && secret.length() > 0)
     364            buf.append(Base64.encode(secret));
     365        buf.append(',');
     366        PrivateKey pk = bd.getAuthPrivKey();
     367        if (pk != null)
     368            buf.append(pk.toBase64());
     369        buf.append(',');
     370        Destination dest = bd.getDestination();
     371        if (dest != null)
     372            buf.append(dest.toBase64());
     373        return buf.toString();
    217374    }
    218375}
Note: See TracChangeset for help on using the changeset viewer.