Skip to content

Instantly share code, notes, and snippets.

@alphazero
Created August 18, 2018 19:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alphazero/7f6737d93fa2cd322cb54ef33900a1ca to your computer and use it in GitHub Desktop.
Save alphazero/7f6737d93fa2cd322cb54ef33900a1ca to your computer and use it in GitHub Desktop.
B2b-resume-perf-fix-diff.java
alphazeroAO ~/Code/java/Blake2b ± diff src/main/java/ove/crypto/digest/Blake2b.java ../githubbers/tim/Blake2b/src/main/java/ove/crypto/digest/Blake2b.java master
22a23
> import java.io.Serializable;
108a110,165
> /**
> * A serializable / JSON-izable object usable for pausing a hash-in-process
> * which can then be resumed with the same Parameter the original digest
> * was constructed with, and fed additional bytes to conclude the hash.
> */
> public static final class ResumeHandle implements Serializable {
> /** per spec */
> public long[] h = new long [ 8 ];
> /** per spec */
> public long[] t = new long [ 2 ];
> /** per spec */
> public long[] f = new long [ 2 ];
> /** per spec (tree) */
> public boolean last_node = false;
> /** pulled up 2b optimal */
> public long[] m = new long [16];
> /** pulled up 2b optimal */
> public long[] v = new long [16];
>
> /** compressor cache buffer */
> public byte[] buffer;
> /** compressor cache buffer offset/cached data length */
> public int buflen;
>
> /** digest length from init param - copied here on init */
> public int outlen;
>
> public int type;
>
> /**
> * Create a reconstituted Black2b digest from
> *
> * @param param
> * @return
> */
> public Blake2b resume(Param param) {
> assert this.buffer != null && this.buffer.length == Spec.block_bytes;
> assert this.h != null && this.h.length == 8
> && this.t != null && this.t.length == 2
> && this.f != null && this.f.length == 2
> && this.m != null && this.m.length == 16
> && this.v != null && this.v.length == 16 : "Data is corrupted";
> assert this.outlen == param.getDigestLength() : "Not originally initialized from this param";
> assert this.type == 1 || this.type == 2 : "Unknown type " + this.type;
> Engine.State state = new Engine.State(outlen, this.type == 1);
> System.arraycopy(this.h, 0, state.h, 0, state.h.length);
> System.arraycopy(this.t, 0, state.t, 0, state.t.length);
> System.arraycopy(this.f, 0, state.f, 0, state.f.length);
> System.arraycopy(this.m, 0, m, 0, m.length);
> System.arraycopy(this.v, 0, v, 0, v.length);
> System.arraycopy(this.buffer, 0, state.buffer, 0, state.buffer.length);
> state.buflen = buflen;
> return type == 1 ? new Mac(param, state) : new Digest(param, state);
> }
> }
>
129a187
> ResumeHandle state();
137a196,198
> private Digest(Param p, State state) {
> super(state, p);
> }
147a209,211
> public static Digest newInstance (Param p, State state) {
> return new Digest(p, state);
> }
155a220
> private Mac (final Param p, State state) { super (state, p); }
277a343,388
> static final class State {
> /** per spec */
> private final long[] h = new long [ 8 ];
> /** per spec */
> private final long[] t = new long [ 2 ];
> /** per spec */
> private final long[] f = new long [ 2 ];
> /** per spec (tree) */
> private boolean last_node = false;
> /** pulled up 2b optimal */
> private final long[] m = new long [16];
> /** pulled up 2b optimal */
> private final long[] v = new long [16];
>
> /** compressor cache buffer */
> private final byte[] buffer;
> /** compressor cache buffer offset/cached data length */
> private int buflen;
>
> /** digest length from init param - copied here on init */
> private final int outlen;
>
> private final int digestType;
>
> State(int digestLength, boolean isMac) {
> this.buffer = new byte [ Spec.block_bytes ];
> this.outlen = digestLength;
> // do not use zero, so we can detect serialization errors
> this.digestType = isMac ? 1 : 2;
> }
>
> public ResumeHandle toResumableForm() {
> ResumeHandle state = new ResumeHandle();
> state.h = h;
> state.t = t;
> state.f = f;
> state.last_node = last_node;
> state.m = m;
> state.v = v;
> state.buffer = buffer;
> state.buflen = buflen;
> state.outlen = outlen;
> state.type = digestType;
> return state;
> }
> }
279,297c390,391
< /** per spec */
< private final long[] h = new long [ 8 ];
< /** per spec */
< private final long[] t = new long [ 2 ];
< /** per spec */
< private final long[] f = new long [ 2 ];
< /** per spec (tree) */
< private boolean last_node = false;
< /** pulled up 2b optimal */
< private final long[] m = new long [16];
< /** pulled up 2b optimal */
< private final long[] v = new long [16];
<
< /** compressor cache buffer */
< private final byte[] buffer;
< /** compressor cache buffer offset/cached data length */
< private int buflen;
<
< /** configuration params */
---
> private State state;
> /** configuration params */
299,302d392
< /** digest length from init param - copied here on init */
< private final int outlen;
< /** to support update(byte) */
< private byte[] oneByte;
311a402,403
> /** to support update(byte) */
> private final byte[] oneByte = new byte[1];
321a414,420
> Engine(State state, Param param) {
> assert state != null : "state is null";
> assert param != null : "param is null";
> this.state = state;
> this.param = param;
> }
>
326,329c425
< this.buffer = new byte [ Spec.block_bytes ];
< this.oneByte = new byte[1];
< this.outlen = param.getDigestLength();
<
---
> state = new State(param.getDigestLength(), this instanceof Mac);
334,337c430,433
< last_node = true;
< assert param.getNodeOffset() == 0 : "root must have offset of zero";
< } else if ( param.getNodeOffset() == param.getFanout() - 1) {
< this.last_node = true;
---
> state.last_node = true;
> assert nxoff == 0 : "root must have offset of zero";
> } else if ( nxoff == param.getFanout() - 1) {
> this.state.last_node = true;
346a443,446
> public ResumeHandle state() {
> return state.toResumableForm();
> }
>
349c449
< System.arraycopy( param.initialized_H(), 0, this.h, 0, Spec.state_space_len);
---
> System.arraycopy( param.initialized_H(), 0, this.state.h, 0, Spec.state_space_len);
372,374c472,474
< this.buflen = 0;
< for(int i=0; i < buffer.length; i++){
< buffer[ i ] = (byte) 0;
---
> this.state.buflen = 0;
> for(int i=0; i < state.buffer.length; i++){
> state.buffer[ i ] = (byte) 0;
378,379c478,479
< this.f[ 0 ] = 0L;
< this.f[ 1 ] = 0L;
---
> this.state.f[ 0 ] = 0L;
> this.state.f[ 1 ] = 0L;
382,383c482,483
< this.t[ 0 ] = 0L;
< this.t[ 1 ] = 0L;
---
> this.state.t[ 0 ] = 0L;
> this.state.t[ 1 ] = 0L;
397a498,499
> final long[] t = state.t;
> final byte[] buffer = state.buffer;
399c501
< if ( buflen == 0) {
---
> if ( state.buflen == 0) {
402,403c504,505
< this.t[0] += Spec.block_bytes;
< this.t[1] += this.t[0] == 0 ? 1 : 0;
---
> t[0] += Spec.block_bytes;
> t[1] += (t[0] < 0 && state.buflen > -t[0]) ? 1 : 0;
408c510
< } else if ( buflen == Spec.block_bytes ) {
---
> } else if ( state.buflen == Spec.block_bytes ) {
410,411c512,513
< this.t[0] += Spec.block_bytes;
< this.t[1] += this.t[0] == 0 ? 1 : 0;
---
> t[0] += Spec.block_bytes;
> t[1] += t[0] == 0 ? 1 : 0;
413c515
< buflen = 0;
---
> state.buflen = 0;
420c522
< final int cap = Spec.block_bytes - buflen;
---
> final int cap = Spec.block_bytes - state.buflen;
422,423c524,525
< System.arraycopy( b, off, buffer, buflen, fill );
< buflen += fill;
---
> System.arraycopy( b, off, buffer, state.buflen, fill );
> state.buflen += fill;
443,449c545,548
< System.arraycopy( zeropad, 0, buffer, buflen, Spec.block_bytes - buflen);
< if(buflen > 0) {
< this.t[0] += buflen;
< /* FIX ISSUE-1 message lengths exceeding 2^64 - credit Axel von dem Bruch (Beloumi@github) */
< // this.t[1] += this.t[0] == 0 ? 1 : 0;
< this.t[1] += (this.t[0] < 0 && buflen > -this.t[0]) ? 1 : 0;
< /* FIX ISSUE-1 END */
---
> System.arraycopy( zeropad, 0, state.buffer, state.buflen, Spec.block_bytes - state.buflen);
> if(state.buflen > 0) {
> this.state.t[0] += state.buflen;
> this.state.t[1] += this.state.t[0] == 0 ? 1 : 0;
452,453c551,552
< this.f[ flag.last_block ] = 0xFFFFFFFFFFFFFFFFL;
< this.f[ flag.last_node ] = this.last_node ? 0xFFFFFFFFFFFFFFFFL : 0x0L;
---
> this.state.f[ flag.last_block ] = 0xFFFFFFFFFFFFFFFFL;
> this.state.f[ flag.last_node ] = this.state.last_node ? 0xFFFFFFFFFFFFFFFFL : 0x0L;
456c555
< compress( buffer, 0 );
---
> compress( state.buffer, 0 );
464,465c563,564
< final byte[] out = new byte [outlen];
< digest ( out, 0, outlen );
---
> final byte[] out = new byte [state.outlen];
> digest ( out, 0, state.outlen );
487a587
> final long[] h = state.h;
518a619
> final long[] m = state.m; // dereference state once - perf. critical [typical for all registers in kernel]
669a771,774
> final long[] v = state.v;
> final long[] h = state.h;
> final long[] t = state.t;
> final long[] f = state.f;
836,839c941,944
< dumpArray("register t", e.t);
< dumpArray("register h", e.h);
< dumpArray("register f", e.f);
< dumpArray("register offset", new long[]{e.buflen});
---
> dumpArray("register t", e.state.t);
> dumpArray("register h", e.state.h);
> dumpArray("register f", e.state.f);
> dumpArray("register offset", new long[]{e.state.buflen});
1027c1132
< private final long[] h = new long [ Spec.state_space_len ];
---
> private final long[] h = new long [ Spec.state_space_len ];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment