/** * Create random symmetric key (AES256, CTR) */ public SymmetricKey() { key = CTRTransformer.randomBytes(32); keyInfo = new KeyInfo(KeyInfo.Algorythm.AES256, null, 32); }
public static SymmetricKey fromPassword(String password, int rounds, byte[] salt) { return new KeyInfo(KeyInfo.PRF.HMAC_SHA256, rounds, salt, null) .derivePassword(password); }
private void setupInfo(byte[] bytes) { keyInfo = new KeyInfo(KeyInfo.Algorythm.RSAPublic, Arrays.copyOfRange(fingerprint(), 1, 6), publicKey.getBitStrength() / 8); }
@Override public KeyRing updateFrom(Binder source) throws IOException, EncryptionError { for(Binder kb: source.getBinders("keys")) { KeyInfo ki = new KeyInfo(kb.getBinary("keyInfo")); AbstractKey k = ki.unpackKey(kb.getBinary("data")); keys.add(k); } return this; }
@Override public final <T> T updateFrom(Binder source) throws IOException { KeyInfo ki = new KeyInfo(source.getBinary("keyInfo")); return (T) ki.unpackKey(source.getBinary("data")); }
/** * Deserialize some key instance from the binder using KeyInfo. Inverse of {@link #toBinder()}. Serialized data are * in binary form and are bit-effective, when using with {@link net.sergeych.boss.Boss} encoders (the default for * Attesta). * * @param binder * from where to restore. * @return ready to use key * @throws IOException * @throws EncryptionError */ static public AbstractKey fromBinder(Binder binder) throws IOException, EncryptionError { KeyInfo info = new KeyInfo(binder.getBinary("keyInfo")); return info.unpackKey(binder.getBinary("data")); }
@Override public KeyInfo info() { if (keyInfo == null) { KeyInfo i = getPublicKey().info(); keyInfo = new KeyInfo(KeyInfo.Algorythm.RSAPrivate, i.getTag(), privateKey .getBitStrength() / 8); } return super.info(); }
public byte[] packWithPassword(String password) throws EncryptionError { byte[] packedKey = pack(); byte[] salt = getClass().getCanonicalName().getBytes(); int rounds = getKDFRounds(); KeyInfo.PRF function = KeyInfo.PRF.HMAC_SHA256; SymmetricKey key = new KeyInfo(function, rounds, salt, null) .derivePassword(password); byte[] packedEncryptedKey = key.encrypt(packedKey); return Boss.dumpToArray(new Object[]{ 2, rounds, salt, function.name(), packedEncryptedKey, new Crc32().update(packedKey).digest() }); }
public static PrivateKey unpackWithPassword(byte[] packedBinary, String password) throws EncryptionError { List params = Boss.load(packedBinary); if ((Integer) params.get(0) == 0) { return new PrivateKey(packedBinary); } else if ((Integer) params.get(0) == 1) { throw new EncryptionError("the key is public, not private"); } else if ((Integer) params.get(0) == 2) { try { int rounds = (int) params.get(1); Bytes salt = (Bytes) params.get(2); String function = (String) params.get(3); Bytes packedEncryptedKey = (Bytes) params.get(4); Bytes digest = (Bytes) params.get(5); SymmetricKey key = new KeyInfo(KeyInfo.PRF.valueOf(function), rounds, salt.getData(), null) .derivePassword(password); byte[] packedKey = key.decrypt(packedEncryptedKey.getData()); byte[] resDigest = new Crc32().update(packedKey).digest(); if (!digest.equals(new Bytes(resDigest))) { throw new PasswordProtectedException("wrong password"); } return new PrivateKey(packedKey); } catch (Exception e) { if (e instanceof PasswordProtectedException) throw e; throw new EncryptionError("failed to parse password protected private key", e); } } else { throw new EncryptionError("Bad or unknown private key type"); } }
@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 decryptWithPassword() throws Exception { Capsule c1 = new Capsule(); c1.setPrivateData("Very", "secret materials"); String password = "icodici forever"; c1.addKeys(new KeyInfo(KeyInfo.PRF.HMAC_SHA256, 1000, null, null).derivePassword(password)); c1.addKeys(new KeyInfo(KeyInfo.PRF.HMAC_SHA256, 1000, null, null).derivePassword(password+"12")); byte[] packed = c1.pack(); Capsule c2 = new Capsule(password, packed); assertEquals(c1, c2); exception.expect(Capsule.DecryptionFailedException.class); new Capsule(password + "bad", packed); }
@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()); }
@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()); }
for (AbstractKey k : keySource.findKey(new KeyInfo(b.getBinary("keyInfo")))) { byte[] encryptedKey = b.getBinary("key"); try {
@Test public void packNoKdf() throws Exception { KeyInfo h1 = new KeyInfo(KeyInfo.Algorythm.RSAPublic, new byte[]{1, 2, 3}, 512); KeyInfo h2 = new KeyInfo(h1.pack()); assertEquals(h1.getAlgorythm(), h2.getAlgorythm()); assertEquals(h1.getPRF(), h2.getPRF()); assertEquals(512, h2.getKeyLength()); h1 = new KeyInfo(KeyInfo.Algorythm.RSAPrivate, new byte[]{4, 2, 3}, 256); h2 = new KeyInfo(h1.pack()); assertEquals(h1.getAlgorythm(), h2.getAlgorythm()); assertEquals(h1.getPRF(), h2.getPRF()); assertEquals(256, h2.getKeyLength()); h1 = new KeyInfo(KeyInfo.Algorythm.AES256, new byte[]{4, 2, 3}, 0); h2 = new KeyInfo(h1.pack()); assertEquals(h1.getAlgorythm(), h2.getAlgorythm()); assertEquals(h1.getPRF(), h2.getPRF());