Changeset 00d4525 for core/java


Ignore:
Timestamp:
Mar 23, 2019 1:39:47 PM (16 months ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
fea5bd4
Parents:
f17776e
Message:

Data: Initial work on b32 format for blinded leasesets (proposal 149, WIP)

Location:
core/java/src/net/i2p
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • core/java/src/net/i2p/client/naming/DummyNamingService.java

    rf17776e r00d4525  
    7070
    7171        // Try Base32 decoding
    72         if (hostname.length() == BASE32_HASH_LENGTH + 8 && hostname.toLowerCase(Locale.US).endsWith(".b32.i2p") &&
     72        if (hostname.length() >= BASE32_HASH_LENGTH + 8 && hostname.toLowerCase(Locale.US).endsWith(".b32.i2p") &&
    7373                _context.getBooleanPropertyDefaultTrue(PROP_B32)) {
    7474            try {
    75                 d = LookupDest.lookupBase32Hash(_context, hostname.substring(0, BASE32_HASH_LENGTH));
     75                if (hostname.length() == BASE32_HASH_LENGTH + 8) {
     76                    // b32
     77                    d = LookupDest.lookupBase32Hash(_context, hostname.substring(0, BASE32_HASH_LENGTH));
     78                } else {
     79                    // b33
     80                    d = LookupDest.lookupHostname(_context, hostname);
     81                }
    7682                if (d != null) {
    7783                    putCache(hostname, d);
  • core/java/src/net/i2p/client/naming/LookupDest.java

    rf17776e r00d4525  
    6060
    6161    /** @param h 32 byte hash */
    62     static Destination lookupHash(I2PAppContext ctx, byte[] h) throws I2PSessionException {
     62    private static Destination lookupHash(I2PAppContext ctx, byte[] h) throws I2PSessionException {
    6363        Hash key = Hash.create(h);
    6464        Destination rv = null;
    6565        I2PClient client = new I2PSimpleClient();
     66        Properties opts = getOpts(ctx);
     67        I2PSession session = null;
     68        try {
     69            session = client.createSession(null, opts);
     70            session.connect();
     71            rv = session.lookupDest(key, DEFAULT_TIMEOUT);
     72        } finally {
     73            if (session != null)
     74                session.destroySession();
     75        }
     76        return rv;
     77    }
     78
     79    /**
     80     * Any hostname, but this is for long-format b32
     81     *
     82     * @param hostname a "b33" hostname, 64+ chars ending with ".b32.i2p"
     83     * @since 0.9.40
     84     */
     85    static Destination lookupHostname(I2PAppContext ctx, String hostname) throws I2PSessionException {
     86        Destination rv = null;
     87        I2PClient client = new I2PSimpleClient();
     88        Properties opts = getOpts(ctx);
     89        I2PSession session = null;
     90        try {
     91            session = client.createSession(null, opts);
     92            session.connect();
     93            rv = session.lookupDest(hostname, DEFAULT_TIMEOUT);
     94        } finally {
     95            if (session != null)
     96                session.destroySession();
     97        }
     98        return rv;
     99    }
     100
     101    /**
     102     * @since 0.9.40 split out from above
     103     */
     104    private static Properties getOpts(I2PAppContext ctx) {
    66105        Properties opts = new Properties();
    67106        if (!ctx.isRouterContext()) {
     
    82121                opts.put(PROP_PW, s);
    83122        }
    84         I2PSession session = null;
    85         try {
    86             session = client.createSession(null, opts);
    87             session.connect();
    88             rv = session.lookupDest(key, DEFAULT_TIMEOUT);
    89         } finally {
    90             if (session != null)
    91                 session.destroySession();
    92         }
    93         return rv;
     123        return opts;
    94124    }
    95125
  • core/java/src/net/i2p/client/naming/MetaNamingService.java

    rf17776e r00d4525  
    104104            return d;
    105105        // Base32 failed?
    106         if (hostname.length() == BASE32_HASH_LENGTH + 8 && hostname.toLowerCase(Locale.US).endsWith(".b32.i2p"))
     106        if (hostname.length() >= BASE32_HASH_LENGTH + 8 && hostname.toLowerCase(Locale.US).endsWith(".b32.i2p"))
    107107            return null;
    108108
  • core/java/src/net/i2p/crypto/Blinding.java

    rf17776e r00d4525  
    55import java.util.Locale;
    66import java.util.TimeZone;
     7import java.util.zip.Checksum;
     8import java.util.zip.CRC32;
    79
    810import net.i2p.I2PAppContext;
     
    1012import net.i2p.crypto.eddsa.EdDSAPrivateKey;
    1113import net.i2p.crypto.eddsa.EdDSAPublicKey;
     14import net.i2p.data.Base32;
     15import net.i2p.data.BlindData;
    1216import net.i2p.data.DataHelper;
    1317import net.i2p.data.Destination;
     
    177181    }
    178182
     183    /**
     184     *  What's the default blinded type for a given unblinded type?
     185     *
     186     *  @return non-null
     187     *  @since 0.9.40
     188     */
     189    public static SigType getDefaultBlindedType(SigType unblindedType) {
     190        if (unblindedType == TYPE)
     191            return TYPER;
     192        return unblindedType;
     193    }
     194
     195    /**
     196     *  Decode a new-format b32 address.
     197     *  PRELIMINARY - Subject to change - see proposal 149
     198     *
     199     *  @param address ending with ".b32.i2p"
     200     *  @throws IllegalArgumentException on bad inputs
     201     *  @throws UnsupportedOperationException unless supported SigTypes
     202     *  @since 0.9.40
     203     */
     204    public static BlindData decode(I2PAppContext ctx, String address) throws RuntimeException {
     205        address = address.toLowerCase(Locale.US);
     206        if (!address.endsWith(".b32.i2p"))
     207            throw new IllegalArgumentException("Not a .b32.i2p address");
     208        byte[] b = Base32.decode(address.substring(0, address.length() - 8));
     209        if (b == null)
     210            throw new IllegalArgumentException("Bad base32 encoding");
     211        if (b.length < 35)
     212            throw new IllegalArgumentException("Not a new-format address");
     213        return decode(ctx, b);
     214    }
     215
     216    /**
     217     *  Decode a new-format b32 address.
     218     *  PRELIMINARY - Subject to change - see proposal 149
     219     *
     220     *  @param b 35+ bytes
     221     *  @throws IllegalArgumentException on bad inputs
     222     *  @throws UnsupportedOperationException unless supported SigTypes
     223     *  @since 0.9.40
     224     */
     225    public static BlindData decode(I2PAppContext ctx, byte[] b) throws RuntimeException {
     226        Checksum crc = new CRC32();
     227        crc.update(b, 3, b.length - 3);
     228        long check = crc.getValue();
     229        b[0] ^= (byte) check;
     230        b[1] ^= (byte) (check >> 8);
     231        b[2] ^= (byte) (check >> 16);
     232        int flag = b[0] & 0xff;
     233        if ((flag & 0xf8) != 0)
     234            throw new IllegalArgumentException("Corrupt b32 or unsupported options");
     235        if ((flag & 0x01) != 0)
     236            throw new IllegalArgumentException("Two byte sig types unsupported");
     237        if ((flag & 0x04) != 0)
     238            throw new IllegalArgumentException("Per-client auth unsupported");
     239        // TODO two-byte sigtypes
     240        int st1 = b[1] & 0xff;
     241        int st2 = b[2] & 0xff;
     242        SigType sigt1 = SigType.getByCode(st1);
     243        SigType sigt2 = SigType.getByCode(st2);
     244        if (sigt1 == null)
     245            throw new IllegalArgumentException("Unknown sig type " + st1);
     246        if (!sigt1.isAvailable())
     247            throw new IllegalArgumentException("Unavailable sig type " + sigt1);
     248        if (sigt2 == null)
     249            throw new IllegalArgumentException("Unknown blinded sig type " + st2);
     250        if (!sigt2.isAvailable())
     251            throw new IllegalArgumentException("Unavailable blinded sig type " + sigt2);
     252        // todo secret/privkey
     253        int spkLen = sigt1.getPubkeyLen();
     254        if (3 + spkLen > b.length)
     255            throw new IllegalArgumentException("b32 too short");
     256        byte[] spkData = new byte[spkLen];
     257        System.arraycopy(b, 3, spkData, 0, spkLen);
     258        SigningPublicKey spk = new SigningPublicKey(sigt1, spkData);
     259        String secret;
     260        if ((flag & 0x02) != 0) {
     261            if (4 + spkLen > b.length)
     262                throw new IllegalArgumentException("No secret data");
     263            int secLen = b[3 + spkLen] & 0xff;
     264            if (4 + spkLen + secLen != b.length)
     265                throw new IllegalArgumentException("Bad b32 length");
     266            secret = DataHelper.getUTF8(b, 4 + spkLen, secLen);
     267        } else if (3 + spkLen != b.length) {
     268            throw new IllegalArgumentException("b32 too long");
     269        } else {
     270            secret = null;
     271        }
     272        BlindData rv = new BlindData(ctx, spk, sigt2, secret);
     273        return rv;
     274    }
     275
     276    /**
     277     *  Encode a public key as a new-format b32 address.
     278     *  PRELIMINARY - Subject to change - see proposal 149
     279     *
     280     *  @param secret may be empty or null
     281     *  @return (56+ chars).b32.i2p
     282     *  @throws IllegalArgumentException on bad inputs
     283     *  @throws UnsupportedOperationException unless supported SigTypes
     284     *  @since 0.9.40
     285     */
     286    public static String encode(I2PAppContext ctx, SigningPublicKey key, String secret) throws RuntimeException {
     287        SigType type = key.getType();
     288        if (type != TYPE && type != TYPER)
     289            throw new UnsupportedOperationException();
     290        byte sdata[] = (secret != null) ? DataHelper.getUTF8(secret) : null;
     291        int slen = (secret != null) ? 1 + sdata.length : 0;
     292        if (slen > 256)
     293            throw new IllegalArgumentException("secret too long");
     294        byte[] d = key.getData();
     295        byte[] b = new byte[d.length + slen + 3];
     296        System.arraycopy(d, 0, b, 3, d.length);
     297        if (slen > 0) {
     298            b[3 + d.length] = (byte) sdata.length;
     299            System.arraycopy(sdata, 0, b, 4 + d.length, sdata.length);
     300        }
     301        Checksum crc = new CRC32();
     302        crc.update(b, 3, b.length - 3);
     303        long check = crc.getValue();
     304        // TODO two-byte sigtypes
     305        if (slen > 0)
     306            b[0] = 0x02;
     307        b[1] = (byte) (type.getCode() & 0xff);
     308        b[2] = (byte) (TYPER.getCode() & 0xff);
     309        b[0] ^= (byte) check;
     310        b[1] ^= (byte) (check >> 8);
     311        b[2] ^= (byte) (check >> 16);
     312        // todo privkey
     313        return Base32.encode(b) + ".b32.i2p";
     314    }
     315
    179316/******
    180317    public static void main(String args[]) throws Exception {
     
    182319        SigningPublicKey pub = (SigningPublicKey) keys[0];
    183320        SigningPrivateKey priv = (SigningPrivateKey) keys[1];
     321        I2PAppContext ctx = I2PAppContext.getGlobalContext();
     322        //String b32 = encode(ctx, pub, null);
     323        String b32 = encode(ctx, pub, "foobarbaz");
     324        System.out.println("pub b32 is " + b32);
     325        BlindData bd = decode(ctx, b32);
     326        if (bd.getBlindedPubKey().equals(pub))
     327            System.out.println("B32 test failed");
     328        else
     329            System.out.println("B32 test passed");
    184330        byte[] b = new byte[64];
    185         net.i2p.I2PAppContext.getGlobalContext().random().nextBytes(b);
     331        ctx.random().nextBytes(b);
    186332        b = EdDSABlinding.reduce(b);
    187333        SigningPrivateKey alpha = new SigningPrivateKey(TYPER, b);
  • core/java/src/net/i2p/data/PrivateKeyFile.java

    rf17776e r00d4525  
    2121import gnu.getopt.Getopt;
    2222
     23import net.i2p.I2PAppContext;
    2324import net.i2p.I2PException;
    2425import net.i2p.client.I2PClient;
     
    2728import net.i2p.client.I2PSessionException;
    2829import net.i2p.client.naming.HostTxtEntry;
     30import net.i2p.crypto.Blinding;
    2931import net.i2p.crypto.DSAEngine;
    3032import net.i2p.crypto.KeyGenerator;
     
    756758        s.append("\nB32: ");
    757759        s.append(this.dest != null ? this.dest.toBase32() : "null");
     760        if (dest != null) {
     761            SigningPublicKey spk = dest.getSigningPublicKey();
     762            SigType type = spk.getType();
     763            if (type == SigType.EdDSA_SHA512_Ed25519 ||
     764                type == SigType.RedDSA_SHA512_Ed25519) {
     765                I2PAppContext ctx = I2PAppContext.getGlobalContext();
     766                s.append("\nBlinded B32: ").append(Blinding.encode(ctx, spk, null));
     767            }
     768        }
    758769        s.append("\nContains: ");
    759770        s.append(this.dest);
Note: See TracChangeset for help on using the changeset viewer.