/** * Finishes encryption and writes down HMAC record. Futhher writing will cause {@link * EOFException}. Does not close the underlying output stream! * * @throws IOException */ public void end() throws IOException { if (done) return; done = true; outputStream.write(hmac.digest()); }
private void end() throws IOException { byte[] readHmac = ring.readAll(); if (readHmac.length != hmac.getLength()) throw new IOException("stream corrupted: bad hmac record size:" + readHmac.length); if (!Arrays.equals(readHmac, hmac.digest())) { throw new AuthenticationFailed("HMAC authentication failed, data corrupted"); } } }
/** * Check that the packed anonymousId matches current key. Use {@link #createAnonymousId()} to get a random anonymous * id for this key. * * @param packedId * @return true if it matches. * @throws IOException */ public boolean matchAnonymousId(@NonNull byte[] packedId) throws IOException { assert (packedId.length == 64); HMAC hmac = new HMAC(fingerprint()); hmac.update(packedId, 0, 32); byte[] idDigest = Arrays.copyOfRange(packedId, 32, 64); return Arrays.equals(hmac.digest(), idDigest); }
/** * Create a random (e.g. every call a different) sequence of bytes that identidy this key. There can almost infinite * number if anonynous ids for e key (more than 1.0E77), so it is really anonymous way to identify some key. The * anonymousId for public and private keys are the same. * <p> * Anonymous ID size is 64 bytes: first are 32 random bytes, last are HMAC(key, sha256) of these random bytes. * <p> * The most important thing about anonymous ids is that every time this call generates new id for the same key, * providing anonymous but exact identification of a key. * <p> * To check that the key matches some anonymousId, use {@link #matchAnonymousId(byte[])}. * <p> * Therefore, the private key fingerprint is its public key fingerprint. The public key fingerprint is calculated * using some hash over it's parameters, see {@link PublicKey#fingerprint()} * * @return */ public byte[] createAnonymousId() { byte[] rvector = Do.randomBytes(32); HMAC hmac = new HMAC(fingerprint()); hmac.update(rvector); byte[] result = new byte[64]; System.arraycopy(rvector, 0, result, 0, 32); System.arraycopy(hmac.digest(), 0, result, 32, 32); return result; }
@Test public void digest() throws Exception { String ok = "la3Xl78Z3ktK2JLoDpPKthhqVilUX6+e6a0WultI9f8="; byte[] key = "1234567890abcdef1234567890abcdef".getBytes(); byte[] data = "a quick brown for his done something disgusting".getBytes(); HMAC hmac = new HMAC(key, Sha256.class); byte[] digest = hmac.digest(data); assertArrayEquals(Base64.decodeLines(ok), digest); // System.out.println(Base64.encodeString(digest)); }