ADD: BLAKE2BP hash function

This commit is contained in:
Alexander Koblov 2018-06-10 10:20:03 +00:00
commit 34632b8556
3 changed files with 498 additions and 16 deletions

View file

@ -3,7 +3,7 @@
Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
Pascal tranlastion in 2014-2015 by Alexander Koblov (alexx2000@mail.ru)
Pascal tranlastion in 2014-2018 by Alexander Koblov (alexx2000@mail.ru)
To the extent possible under law, the author(s) have dedicated all copyright
and related and neighboring rights to this software to the public domain
@ -25,12 +25,20 @@ uses
SysUtils, CTypes;
const
PARALLELISM_DEGREE = 8;
BLAKE2S_BLOCKBYTES = 64;
BLAKE2S_OUTBYTES = 32;
BLAKE2S_KEYBYTES = 32;
BLAKE2S_SALTBYTES = 8;
BLAKE2S_PERSONALBYTES = 8;
BLAKE2S_PARALLELISM_DEGREE = 8;
const
BLAKE2B_BLOCKBYTES = 128;
BLAKE2B_OUTBYTES = 64;
BLAKE2B_KEYBYTES = 64;
BLAKE2B_SALTBYTES = 16;
BLAKE2B_PERSONALBYTES = 16;
BLAKE2B_PARALLELISM_DEGREE = 4;
type
{$packrecords 1}
@ -69,6 +77,43 @@ type
inp: PByte;
end;
{$packrecords default}
Pblake2b_state = ^blake2b_state;
blake2b_state = record
h: array[0..7] of cuint64;
t: array[0..1] of cuint64;
f: array[0..1] of cuint64;
buf: array [0..Pred(BLAKE2B_BLOCKBYTES)] of cuint8;
buflen: csize_t;
outlen: csize_t;
last_node: cuint8;
end;
{$packrecords 1}
Pblake2b_param = ^blake2b_param;
blake2b_param = record
digest_length: uint8; // 1
key_length: cuint8; // 2
fanout: cuint8; // 3
depth: cuint8; // 4
leaf_length: cuint32; // 8
node_offset: cuint32; // 12
xof_length: cuint32; // 16
node_depth: cuint8; // 17
inner_length: cuint8; // 18
reserved: array[0..13] of cuint8; // 32
salt: array [0..Pred(BLAKE2B_SALTBYTES)] of cuint8; // 48
personal: array[0..Pred(BLAKE2B_PERSONALBYTES)] of cuint8; // 64
end;
{$packrecords default}
Pblake2bp_state = ^blake2bp_state;
blake2bp_state = record
S: array[0..3] of blake2b_state;
R: blake2b_state;
buf: array[0..Pred(4 * BLAKE2B_BLOCKBYTES)] of cuint8;
buflen: csize_t;
outlen: csize_t;
inlen: csize_t;
inp: PByte;
end;
function blake2s_init( S: Pblake2s_state; const outlen: cuint8 ): cint;
function blake2s_update( S: Pblake2s_state; inp: pcuint8; inlen: cuint64 ): cint;
@ -78,6 +123,14 @@ function blake2sp_init( S: Pblake2sp_state; const outlen: cuint8 ): cint;
function blake2sp_update( S: Pblake2sp_state; inp: pcuint8; inlen: cuint64 ): cint;
function blake2sp_final( S: Pblake2sp_state; outp: pcuint8; const outlen: cuint8 ): cint;
function blake2b_init( S: Pblake2b_state; outlen: csize_t ): cint;
function blake2b_update( S: Pblake2b_state; pin: pcuint8; inlen: csize_t ): cint;
function blake2b_final( S: Pblake2b_state; pout: pcuint8; outlen: csize_t ): cint;
function blake2bp_init( S: Pblake2bp_state; outlen: csize_t ): cint;
function blake2bp_update( S: Pblake2bp_state; inp: pcuint8; inlen: csize_t ): cint;
function blake2bp_final( S: Pblake2bp_state; out_: PByte; outlen: csize_t ): cint;
implementation
{$IF DEFINED(USE_MTPROCS)}
@ -94,6 +147,30 @@ const blake2s_IV: array[0..7] of cuint32 =
$510E527F, $9B05688C, $1F83D9AB, $5BE0CD19
);
const blake2b_IV: array[0..7] of cint64 =
(
$6a09e667f3bcc908, $bb67ae8584caa73b,
$3c6ef372fe94f82b, $a54ff53a5f1d36f1,
$510e527fade682d1, $9b05688c2b3e6c1f,
$1f83d9abfb41bd6b, $5be0cd19137e2179
);
const blake2b_sigma: array[0..11] of array[0..15] of cuint8 =
(
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ) ,
( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 ) ,
( 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 ) ,
( 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 ) ,
( 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 ) ,
( 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 ) ,
( 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 ) ,
( 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 ) ,
( 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 ) ,
( 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 ) ,
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 ) ,
( 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 )
);
function load32( const src: Pointer ): cuint32; inline;
begin
Result := NtoLE(pcuint32(src)^);
@ -297,7 +374,7 @@ var
begin
P.digest_length := outlen;
P.key_length := keylen;
P.fanout := PARALLELISM_DEGREE;
P.fanout := BLAKE2S_PARALLELISM_DEGREE;
P.depth := 2;
store32( @P.leaf_length, 0 );
store48( @P.node_offset[0], offset );
@ -314,7 +391,7 @@ var
begin
P.digest_length := outlen;
P.key_length := keylen;
P.fanout := PARALLELISM_DEGREE;
P.fanout := BLAKE2S_PARALLELISM_DEGREE;
P.depth := 2;
store32( @P.leaf_length, 0 );
store48( @P.node_offset[0], 0 );
@ -336,11 +413,11 @@ begin
if( blake2sp_init_root( @S^.R, outlen, 0 ) < 0 ) then Exit(-1);
for i := 0 to PARALLELISM_DEGREE - 1 do
for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do
if ( blake2sp_init_leaf( @S^.S[i], outlen, 0, i ) < 0 ) then Exit(-1);
S^.R.last_node := 1;
S^.S[PARALLELISM_DEGREE - 1].last_node := 1;
S^.S[BLAKE2S_PARALLELISM_DEGREE - 1].last_node := 1;
Result := 0;
end;
@ -354,11 +431,11 @@ begin
inlen__ := S^.inlen;
in__ += id__ * BLAKE2S_BLOCKBYTES;
while ( inlen__ >= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ) do
while ( inlen__ >= BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES ) do
begin
blake2s_update( @S^.S[id__], in__, BLAKE2S_BLOCKBYTES );
in__ += PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
inlen__ -= PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
in__ += BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
inlen__ -= BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES;
end;
end;
@ -373,7 +450,7 @@ begin
begin
Move(inp^, S^.buf[left], fill);
for i := 0 to PARALLELISM_DEGREE - 1 do
for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do
blake2s_update( @S^.S[i], @S^.buf[ i * BLAKE2S_BLOCKBYTES], BLAKE2S_BLOCKBYTES );
inp += fill;
@ -385,13 +462,13 @@ begin
S^.inlen := inlen;
{$IF DEFINED(USE_MTPROCS)}
ProcThreadPool.DoParallel(@MTProcedure, 0, PARALLELISM_DEGREE - 1, S);
ProcThreadPool.DoParallel(@MTProcedure, 0, BLAKE2S_PARALLELISM_DEGREE - 1, S);
{$ELSE}
for i := 0 to PARALLELISM_DEGREE - 1 do MTProcedure(i, S, nil);
{$ENDIF}
inp += inlen - inlen mod ( PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
inlen := inlen mod (PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES);
inp += inlen - inlen mod ( BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES );
inlen := inlen mod (BLAKE2S_PARALLELISM_DEGREE * BLAKE2S_BLOCKBYTES);
if ( inlen > 0 ) then
Move(inp^, S^.buf[left], inlen );
@ -403,10 +480,10 @@ end;
function blake2sp_final( S: Pblake2sp_state; outp: pcuint8; const outlen: cuint8 ): cint;
var
i, left: csize_t;
hash: array[0..Pred(PARALLELISM_DEGREE), 0..Pred(BLAKE2S_OUTBYTES)] of cuint8;
hash: array[0..Pred(BLAKE2S_PARALLELISM_DEGREE), 0..Pred(BLAKE2S_OUTBYTES)] of cuint8;
begin
for i := 0 to PARALLELISM_DEGREE - 1 do
for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do
begin
if ( S^.buflen > i * BLAKE2S_BLOCKBYTES ) then
begin
@ -420,11 +497,347 @@ begin
blake2s_final( @S^.S[i], hash[i], BLAKE2S_OUTBYTES );
end;
for i := 0 to PARALLELISM_DEGREE - 1 do
for i := 0 to BLAKE2S_PARALLELISM_DEGREE - 1 do
blake2s_update( @S^.R, hash[i], BLAKE2S_OUTBYTES );
blake2s_final( @S^.R, outp, outlen );
Result := 0;
end;
procedure blake2b_set_lastnode( S: Pblake2b_state ); inline;
begin
S^.f[1] := cuint64(-1);
end;
//* Some helper functions, not necessarily useful */
function blake2b_is_lastblock( S: Pblake2b_state ): cint; inline;
begin
Result := cint(S^.f[0] <> 0);
end;
procedure blake2b_set_lastblock( S: Pblake2b_state );
begin
if( S^.last_node <> 0 ) then blake2b_set_lastnode( S );
S^.f[0] := cuint64(-1);
end;
procedure blake2b_increment_counter( S: Pblake2b_state; const inc: cuint64 );
begin
S^.t[0] += inc;
S^.t[1] += cuint64( S^.t[0] < inc );
end;
procedure blake2b_init0( S: Pblake2b_state );
var
i: csize_t;
begin
fillchar( S^, sizeof( blake2b_state ), 0 );
for i := 0 to 7 do S^.h[i] := cuint64(blake2b_IV[i]);
end;
//* init xors IV with input parameter block */
function blake2b_init_param( S: Pblake2b_state; const P: Pblake2b_param ): cint;
var
i: csize_t;
pp: pcuint8;
begin
pp := pcuint8( P );
blake2b_init0( S );
//* IV XOR ParamBlock */
for i := 0 to 7 do
S^.h[i] := S^.h[i] xor load64( pp + sizeof( S^.h[i] ) * i );
S^.outlen := P^.digest_length;
Result := 0;
end;
function blake2b_init( S: Pblake2b_state; outlen: csize_t ): cint;
var
P: blake2b_param;
begin
if ( ( outlen = 0 ) or ( outlen > BLAKE2B_OUTBYTES ) ) then Exit(-1);
P.digest_length := cuint8(outlen);
P.key_length := 0;
P.fanout := 1;
P.depth := 1;
store32( @P.leaf_length, 0 );
store32( @P.node_offset, 0 );
store32( @P.xof_length, 0 );
P.node_depth := 0;
P.inner_length := 0;
fillchar( P.reserved, sizeof( P.reserved ), 0 );
fillchar( P.salt, sizeof( P.salt ), 0 );
fillchar( P.personal, sizeof( P.personal ), 0 );
Result := blake2b_init_param( S, @P );
end;
procedure blake2b_compress( S: Pblake2b_state; const block: pcuint8 );
var
i: csize_t;
m: array[0..15] of cuint64;
v: array[0..15] of cuint64;
procedure G( r, i: cuint64; var a, b, c, d: cuint64 ); inline;
begin
a := a + b + m[blake2b_sigma[r][2 * i + 0]];
d := RorQWord(d xor a, 32);
c := c + d;
b := RorQWord(b xor c, 24);
a := a + b + m[blake2b_sigma[r][2 * i + 1]];
d := RorQWord(d xor a, 16);
c := c + d;
b := RorQWord(b xor c, 63);
end;
{$define ROUND_MACRO:=
G(r_,0,v[ 0],v[ 4],v[ 8],v[12]);
G(r_,1,v[ 1],v[ 5],v[ 9],v[13]);
G(r_,2,v[ 2],v[ 6],v[10],v[14]);
G(r_,3,v[ 3],v[ 7],v[11],v[15]);
G(r_,4,v[ 0],v[ 5],v[10],v[15]);
G(r_,5,v[ 1],v[ 6],v[11],v[12]);
G(r_,6,v[ 2],v[ 7],v[ 8],v[13]);
G(r_,7,v[ 3],v[ 4],v[ 9],v[14]);
}
begin
for i := 0 to 15 do
m[i] := load64( block + i * sizeof( m[i] ) );
for i := 0 to 7 do
v[i] := S^.h[i];
v[ 8] := cuint64(blake2b_IV[0]);
v[ 9] := cuint64(blake2b_IV[1]);
v[10] := cuint64(blake2b_IV[2]);
v[11] := cuint64(blake2b_IV[3]);
v[12] := cuint64(blake2b_IV[4] xor S^.t[0]);
v[13] := cuint64(blake2b_IV[5] xor S^.t[1]);
v[14] := cuint64(blake2b_IV[6] xor S^.f[0]);
v[15] := cuint64(blake2b_IV[7] xor S^.f[1]);
{$define r_:= 0} ROUND_MACRO;
{$define r_:= 1} ROUND_MACRO;
{$define r_:= 2} ROUND_MACRO;
{$define r_:= 3} ROUND_MACRO;
{$define r_:= 4} ROUND_MACRO;
{$define r_:= 5} ROUND_MACRO;
{$define r_:= 6} ROUND_MACRO;
{$define r_:= 7} ROUND_MACRO;
{$define r_:= 8} ROUND_MACRO;
{$define r_:= 9} ROUND_MACRO;
{$define r_:= 10} ROUND_MACRO;
{$define r_:= 11} ROUND_MACRO;
for i := 0 to 7 do
S^.h[i] := S^.h[i] xor v[i] xor v[i + 8];
end;
function blake2b_update( S: Pblake2b_state; pin: pcuint8; inlen: csize_t ): cint;
var
left, fill: csize_t;
begin
if ( inlen > 0 ) then
begin
left := S^.buflen;
fill := BLAKE2B_BLOCKBYTES - left;
if ( inlen > fill ) then
begin
S^.buflen := 0;
Move( pin^, S^.buf[left], fill ); //* Fill buffer */
blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
blake2b_compress( S, S^.buf ); //* Compress */
pin += fill; inlen -= fill;
while (inlen > BLAKE2B_BLOCKBYTES) do
begin
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress( S, pin );
pin += BLAKE2B_BLOCKBYTES;
inlen -= BLAKE2B_BLOCKBYTES;
end
end;
Move( pin^, S^.buf[S^.buflen], inlen );
S^.buflen += inlen;
end;
Result := 0;
end;
function blake2b_final( S: Pblake2b_state; pout: pcuint8; outlen: csize_t ): cint;
var
i: csize_t;
buffer: array[0..Pred(BLAKE2B_OUTBYTES)] of cuint8;
begin
if( pout = nil) or (outlen < S^.outlen ) then
Exit(-1);
if ( blake2b_is_lastblock( S ) <> 0 ) then
Exit(-1);
fillchar(buffer[0], BLAKE2B_OUTBYTES, 0);
blake2b_increment_counter( S, S^.buflen );
blake2b_set_lastblock( S );
fillchar( S^.buf[S^.buflen], BLAKE2B_BLOCKBYTES - S^.buflen, 0 ); //* Padding */
blake2b_compress( S, S^.buf );
for i := 0 to 7 do //* Output full hash to temp buffer */
store64( @buffer[sizeof( S^.h[i] ) * i], S^.h[i] );
move( buffer[0], pout^, S^.outlen );
fillchar(buffer[0], sizeof(buffer), 0);
Result := 0;
end;
function blake2bp_init_leaf_param( S: Pblake2b_state; const P: Pblake2b_param ): cint;
begin
Result:= blake2b_init_param(S, P);
S^.outlen := P^.inner_length;
end;
function blake2bp_init_leaf( S: Pblake2b_state; outlen, keylen: csize_t; offset: cuint64 ): cint;
var
P: blake2b_param;
begin
P.digest_length := cuint8(outlen);
P.key_length := cuint8(keylen);
P.fanout := BLAKE2B_PARALLELISM_DEGREE;
P.depth := 2;
store32( @P.leaf_length, 0 );
store32( @P.node_offset, offset );
store32( @P.xof_length, 0 );
P.node_depth := 0;
P.inner_length := BLAKE2B_OUTBYTES;
FillChar( P.reserved[0], sizeof( P.reserved ), 0 );
FillChar( P.salt[0], sizeof( P.salt ), 0 );
FillChar( P.personal[0], sizeof( P.personal ), 0 );
Result:= blake2bp_init_leaf_param( S, @P );
end;
function blake2bp_init_root( S: Pblake2b_state; outlen, keylen: csize_t ): cint;
var
P: blake2b_param;
begin
P.digest_length := cuint8(outlen);
P.key_length := cuint8(keylen);
P.fanout := BLAKE2B_PARALLELISM_DEGREE;
P.depth := 2;
store32( @P.leaf_length, 0 );
store32( @P.node_offset, 0 );
store32( @P.xof_length, 0 );
P.node_depth := 1;
P.inner_length := BLAKE2B_OUTBYTES;
FillChar( P.reserved[0], sizeof( P.reserved ), 0 );
FillChar( P.salt[0], sizeof( P.salt ), 0 );
FillChar( P.personal[0], sizeof( P.personal ), 0 );
Result:= blake2b_init_param( S, @P );
end;
function blake2bp_init( S: Pblake2bp_state; outlen: csize_t ): cint;
var
i: csize_t;
begin
if (outlen = 0) or (outlen > BLAKE2B_OUTBYTES) then Exit(-1);
FillChar( S^.buf[0], sizeof( S^.buf ), 0 );
S^.buflen := 0;
S^.outlen := outlen;
if( blake2bp_init_root( @S^.R, outlen, 0 ) < 0 ) then
Exit(-1);
for i := 0 to BLAKE2B_PARALLELISM_DEGREE - 1 do
if ( blake2bp_init_leaf( @S^.S[i], outlen, 0, i ) < 0 ) then Exit(-1);
S^.R.last_node := 1;
S^.S[BLAKE2B_PARALLELISM_DEGREE - 1].last_node := 1;
Result:= 0;
end;
procedure blake2bp_MTProcedure(i: PtrInt; Data: Pointer; Item: TMultiThreadProcItem);
var
in__: pcuint8;
inlen__: cuint64;
S: Pblake2bp_state absolute Data;
begin
in__ := S^.inp;
inlen__ := S^.inlen;
in__ += i * BLAKE2B_BLOCKBYTES;
while ( inlen__ >= BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES ) do
begin
blake2b_update( @S^.S[i], in__, BLAKE2B_BLOCKBYTES );
in__ += BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
inlen__ -= BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES;
end;
end;
function blake2bp_update( S: Pblake2bp_state; inp: pcuint8; inlen: csize_t ): cint;
var
left, fill, i: csize_t;
begin
left := S^.buflen;
fill := sizeof( S^.buf ) - left;
if( left > 0) and (inlen >= fill ) then
begin
Move( inp^, S^.buf[left], fill );
for i := 0 to BLAKE2B_PARALLELISM_DEGREE - 1 do
blake2b_update( @S^.S[i], @S^.buf[i * BLAKE2B_BLOCKBYTES], BLAKE2B_BLOCKBYTES );
inp += fill;
inlen -= fill;
left := 0;
end;
S^.inp := inp;
S^.inlen := inlen;
{$IF DEFINED(USE_MTPROCS)}
ProcThreadPool.DoParallel(@blake2bp_MTProcedure, 0, BLAKE2B_PARALLELISM_DEGREE - 1, S);
{$ELSE}
for i := 0 to BLAKE2B_PARALLELISM_DEGREE - 1 do blake2bp_MTProcedure(i, S, nil);
{$ENDIF}
inp += inlen - inlen mod ( BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES );
inlen := inlen mod (BLAKE2B_PARALLELISM_DEGREE * BLAKE2B_BLOCKBYTES);
if ( inlen > 0 ) then
Move( inp^, S^.buf[left], inlen );
S^.buflen := left + inlen;
Result:= 0;
end;
function blake2bp_final( S: Pblake2bp_state; out_: PByte; outlen: csize_t ): cint;
var
i, left: csize_t;
hash: array[0..Pred(BLAKE2B_PARALLELISM_DEGREE), 0..Pred(BLAKE2B_OUTBYTES)] of cuint8;
begin
if (out_ = nil) or (outlen < S^.outlen) then Exit(-1);
for i := 0 to BLAKE2B_PARALLELISM_DEGREE - 1 do
begin
if ( S^.buflen > i * BLAKE2B_BLOCKBYTES ) then
begin
left := S^.buflen - i * BLAKE2B_BLOCKBYTES;
if ( left > BLAKE2B_BLOCKBYTES ) then left := BLAKE2B_BLOCKBYTES;
blake2b_update( @S^.S[i], @S^.buf[i * BLAKE2B_BLOCKBYTES], left );
end;
blake2b_final( @S^.S[i], hash[i], BLAKE2B_OUTBYTES );
end;
for i := 0 to BLAKE2B_PARALLELISM_DEGREE -1 do
blake2b_update( @S^.R, hash[i], BLAKE2B_OUTBYTES );
Result:= blake2b_final( @S^.R, out_, S^.outlen );
end;
end.

View file

@ -81,6 +81,22 @@ type
procedure Final(var Digest); override;
end;
{ TDCP_blake2bp }
TDCP_blake2bp = class(TDCP_hash)
protected
S: blake2bp_state;
public
class function GetId: integer; override;
class function GetAlgorithm: string; override;
class function GetHashSize: integer; override;
class function SelfTest: boolean; override;
procedure Init; override;
procedure Burn; override;
procedure Update(const Buffer; Size: longword); override;
procedure Final(var Digest); override;
end;
implementation
{ TDCP_blake2s }
@ -283,5 +299,57 @@ begin
Burn;
end;
{ TDCP_blake2bp }
class function TDCP_blake2bp.GetId: integer;
begin
Result:= DCP_blake2bp;
end;
class function TDCP_blake2bp.GetAlgorithm: string;
begin
Result:= 'BLAKE2BP';
end;
class function TDCP_blake2bp.GetHashSize: integer;
begin
Result:= 512;
end;
class function TDCP_blake2bp.SelfTest: boolean;
begin
Result:= False;
end;
procedure TDCP_blake2bp.Init;
begin
if blake2bp_init( @S, BLAKE2B_OUTBYTES ) < 0 then
raise EDCP_hash.Create('blake2bp_init');
fInitialized:= true;
end;
procedure TDCP_blake2bp.Burn;
begin
fInitialized:= false;
end;
procedure TDCP_blake2bp.Update(const Buffer; Size: longword);
begin
if blake2bp_update(@S, @Buffer, Size) < 0 then
raise EDCP_hash.Create('blake2bp_update');
end;
procedure TDCP_blake2bp.Final(var Digest);
var
Hash: array[0..Pred(BLAKE2B_OUTBYTES)] of cuint8;
begin
if not fInitialized then
raise EDCP_hash.Create('Hash not initialized');
if blake2bp_final(@S, Hash, SizeOf(Hash)) < 0 then
raise EDCP_hash.Create('blake2bp_final');
Move(Hash, Digest, Sizeof(Hash));
Burn;
end;
end.

View file

@ -63,6 +63,7 @@ const
DCP_sha256 = 28;
DCP_sha384 = 29;
DCP_sha512 = 30;
DCP_blake2bp = 95;
DCP_blake2b = 96;
DCP_blake2s = 97;
DCP_blake2sp = 98;