jvz commented on a change in pull request #79:
URL: https://github.com/apache/commons-codec/pull/79#discussion_r589593083



##########
File path: src/main/java/org/apache/commons/codec/digest/Blake3.java
##########
@@ -0,0 +1,455 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.codec.digest;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Implements the Blake3 algorithm providing a {@linkplain #initHash() hash 
function} with extensible output (XOF), a
+ * {@linkplain #initKeyedHash(byte[]) keyed hash function} (MAC, PRF), and a
+ * {@linkplain #initKeyDerivationFunction(byte[]) key derivation function} 
(KDF). Blake3 has a 128-bit security level
+ * and a default output length of 256 bits (32 bytes) which can extended up to 
2<sup>64</sup> bytes.
+ * <p>
+ * Adapted from the ISC-licensed O(1) Cryptography library by Matt Sicker and 
ported from the reference public domain
+ * implementation by Jack O'Connor.
+ * </p>
+ *
+ * @see <a href="https://github.com/BLAKE3-team/BLAKE3";>BLAKE3 hash 
function</a>
+ * @since 1.16
+ */
+public final class Blake3 {
+    // TODO: migrate to Integer.BYTES after upgrading to Java 8
+    private static final int INT_BYTES = Integer.SIZE / Byte.SIZE;
+
+    private static final int BLOCK_LEN = 64;
+    private static final int KEY_LEN = 32;
+    private static final int OUT_LEN = 32;
+    private static final int CHUNK_LEN = 1024;
+
+    private static final int[] IV =
+            { 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 
0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 };
+
+    // domain flags
+    private static final int CHUNK_START = 1;
+    private static final int CHUNK_END = 1 << 1;
+    private static final int PARENT = 1 << 2;
+    private static final int ROOT = 1 << 3;
+    private static final int KEYED_HASH = 1 << 4;
+    private static final int DERIVE_KEY_CONTEXT = 1 << 5;
+    private static final int DERIVE_KEY_MATERIAL = 1 << 6;
+
+    private final EngineState engineState;
+
+    private Blake3(final int[] key, final int flags) {
+        engineState = new EngineState(key, flags);
+    }
+
+    /**
+     * Resets this instance back to its initial state when it was first 
constructed.
+     */
+    public void reset() {
+        engineState.reset();
+    }
+
+    /**
+     * Absorbs the provided bytes into this instance's state.
+     *
+     * @param in source array to absorb data from
+     */
+    public void absorb(final byte[] in) {
+        Objects.requireNonNull(in);
+        absorb(in, 0, in.length);
+    }
+
+    /**
+     * Absorbs the provided bytes at an offset into this instance's state.
+     *
+     * @param in     source array to absorb data from
+     * @param offset where in the array to begin absorbing bytes
+     * @param length number of bytes to absorb in
+     */
+    public void absorb(final byte[] in, final int offset, final int length) {
+        Objects.requireNonNull(in);
+        engineState.inputData(in, offset, length);
+    }
+
+    /**
+     * Squeezes hash output data that depends on the sequence of absorbed 
bytes preceding this invocation and any previously
+     * squeezed bytes.
+     *
+     * @param out destination array to squeeze bytes into
+     */
+    public void squeeze(final byte[] out) {

Review comment:
       The original name for this method is `finalize` which doesn't mesh too 
well with Java (similar to why the crypto APIs use `doFinal()` instead of 
`final()`). Perhaps I could use `doFinalize()`? This method is used for 
calculating the hash and can be done incrementally (e.g., knowing the hash of a 
part of a file as it's streaming) and being an extensible output function, this 
can "squeeze" as many bytes as requested to create an arbitrarily long hash (up 
to 2^64 bytes I think).
   
   The squeeze/absorb naming is something I borrowed from internals of SHA-3, 
so I'm certainly up for renaming them to something else. Absorb is equivalent 
to `update` in `MessageDigest` and `Mac`.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to