@Test public void packKdf() throws Exception { KeyInfo h1 = new KeyInfo(KeyInfo.PRF.HMAC_SHA256, 4096, null, null); KeyInfo h2 = new KeyInfo(h1.pack()); assertEquals(h1.getAlgorythm(), h2.getAlgorythm()); assertEquals(h1.getPRF(), h2.getPRF()); assertEquals(h1.getRounds(), h2.getRounds()); assertEquals(h1.getKeyLength(), h2.getKeyLength()); assertEquals(KeyInfo.PRF.HMAC_SHA256, h2.getPRF()); assertEquals(KeyInfo.Algorythm.AES256, h2.getAlgorythm()); assertArrayEquals(h1.getTag(), h2.getTag()); }
@Override public String toString() { AbstractKey k = this instanceof PrivateKey ? getPublicKey() : this; return info().toString() + ":" + info().getBase64Tag(); }
public static SymmetricKey fromPassword(String password, int rounds, byte[] salt) { return new KeyInfo(KeyInfo.PRF.HMAC_SHA256, rounds, salt, null) .derivePassword(password); }
@Override public Collection<AbstractKey> findKey(KeyInfo keyInfo) { ArrayList<AbstractKey> list = new ArrayList<>(); if (keyInfo.isPassword()) list.add(keyInfo.derivePassword(password)); return list; } };
keys.forEach(k -> { KeyInfo i = k.info(); report("\t✔︎ " + i.getAlgorythm() + ":" + i.getKeyLength() * 8 + ":" + i.getBase64Tag()); }); report("\nWhich can play roles:\n");
@Test public void privateKeyMustHaveInfo() throws Exception { AbstractKey prk = TestKeys.privateKey(3); AbstractKey puk = prk.getPublicKey(); KeyInfo h = prk.info(); assertEquals(KeyInfo.Algorythm.RSAPrivate, h.getAlgorythm()); assertEquals(KeyInfo.PRF.None, h.getPRF()); assertEquals(5, h.getTag().length); assertArrayEquals(puk.info().getTag(), h.getTag()); // Bytes.dump(h.pack()); }
@Test public void deriveKey() throws Exception { KeyInfo h1 = new KeyInfo(KeyInfo.PRF.HMAC_SHA256, 4096, null, null); KeyInfo h2 = new KeyInfo(h1.pack()); assertArrayEquals(h1.getSalt(), h2.getSalt()); assertArrayEquals("attesta".getBytes(), h2.getSalt()); SymmetricKey k = h1.derivePassword("elegance"); byte[] k1 = PBKDF2.derive(Sha256.class, "elegance", "attesta".getBytes(), 4096, 32); assertArrayEquals(k1, k.getKey()); assertEquals(h1, k.info()); }
@Test public void symmetricKeyMustHaveRightInfo() { SymmetricKey k = new SymmetricKey(); KeyInfo h = k.info(); assertEquals(KeyInfo.Algorythm.AES256, h.getAlgorythm()); assertEquals(32, h.getKeyLength()); assertEquals(KeyInfo.PRF.None, h.getPRF()); }
/** * Each supported key has a mask that represents its type. The key that has no known mask can't be processed bt the * address. * * @param k * key to calculate mask of. * * @return */ protected static int mask(AbstractKey k) { KeyInfo i = k.info(); switch (i.getAlgorythm()) { case RSAPublic: case RSAPrivate: if (((PublicKey) k).getPublicExponent() == 0x10001) { int l = i.getKeyLength(); if (l == 2048 / 8) return 0x01; if (l == 4096 / 8) return 0x02; } break; } throw new IllegalArgumentException("key can't be masked for address: " + i); }
@Test public void findKey() throws Exception { KeyInfo i1 = new KeyInfo(KeyInfo.PRF.HMAC_SHA256, 1024, null, null); AbstractKey pk1 = i1.derivePassword("helluva"); KeyInfo i2 = new KeyInfo(KeyInfo.PRF.HMAC_SHA256, 1025, null, "the tag".getBytes()); AbstractKey pk2 = i2.derivePassword("helluva"); assertEquals(i2.getTag(), pk2.info().getTag()); KeyRing kr = new KeyRing(); SymmetricKey sk1 = new SymmetricKey(); SymmetricKey sk2 = new SymmetricKey(); AbstractKey privateKey = TestKeys.privateKey(0); AbstractKey publicKey1 =TestKeys.privateKey(1).getPublicKey(); AbstractKey publicKey2 = privateKey.getPublicKey(); kr.addKeys( sk1, sk2, privateKey, publicKey1, publicKey2, pk1, pk2 ); kr.addKeys(pk1, pk2); Binder b = kr.toBinder(); KeyRing kr2 = KeyRing.fromBinder(b); assertTrue(kr.keySet().contains(pk1)); assertTrue(kr.keySet().contains(pk2)); assertEquals(pk2, kr.findKey(i2).toArray()[0]); assertEquals(pk2, kr2.findKey(i2).toArray()[0]); final Collection<AbstractKey> keys = kr.findKey(i1); assertTrue(keys.contains(pk1)); assertTrue(keys.contains(pk1)); assertTrue(keys.contains(sk1)); assertTrue(keys.contains(sk2)); assertEquals(4, kr2.findKey(i1).size()); }
/** * The smart keys search. First keys with matching tags and type, then all others with matching * type. * * @param keyInfo desired key information * @return Collection of matching keys, possibly empty. */ @Override @NonNull public Collection<AbstractKey> findKey(KeyInfo keyInfo) { final ArrayList<AbstractKey> result = new ArrayList<>(); for( AbstractKey k: keys) { final KeyInfo ki = k.info(); if( ki.matchType(keyInfo) ) { if( ki.matchTag(keyInfo) ) result.add(0, k); else result.add(k); } } return result; }
@Override public Collection<AbstractKey> findKey(KeyInfo keyInfo) { ArrayList results = new ArrayList(); if (info().matchType(keyInfo)) results.add(AbstractKey.this); return results; } };
/** * Create random symmetric key (AES256, CTR) */ public SymmetricKey() { key = CTRTransformer.randomBytes(32); keyInfo = new KeyInfo(KeyInfo.Algorythm.AES256, null, 32); }
sealedByKeys.put(key, es); } else addError(Errors.BAD_SIGNATURE, "keytag:" + key.info().getBase64Tag(), "the signature is broken");
public byte[] packedInfo() { return info().pack(); }
public String getBase64Tag() { return Base64.encodeCompactString(getTag()); }
public boolean matchTag(AbstractKey other) { return info().matchTag(other.info()); }
@Test public void handshakeAndSecureCommand() throws Exception { PrivateKey nodeKey = TestKeys.privateKey(1); PrivateKey clientKey = TestKeys.privateKey(2); BasicHttpServer s = new BasicHttpServer(nodeKey, 15600, 32, log); BasicHttpClient c = new BasicHttpClient("http://localhost:15600"); c.start(clientKey, nodeKey.getPublicKey(), null); Binder res = c.command("sping"); assertEquals("spong", res.getStringOrThrow("sping")); s.addSecureEndpoint("getSessionInfo", (params,session)-> { // System.out.println("in sec, "+session); // System.out.println("\t "+session.getPublicKey()); return Binder.of("publicKey", session.getPublicKey().info().toString()); }); res = c.command("getSessionInfo"); s.shutdown(); }