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; } };
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 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 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 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()); }