diff --git a/lib/cryptography_utils.dart b/lib/cryptography_utils.dart index eea2d787..07ce3447 100644 --- a/lib/cryptography_utils.dart +++ b/lib/cryptography_utils.dart @@ -5,7 +5,7 @@ export 'src/cdsa/cdsa.dart'; export 'src/hash/hmac.dart'; export 'src/hash/keccak/keccak.dart'; export 'src/hash/pbkdf2.dart'; -export 'src/hash/ripemd160.dart'; +export 'src/hash/ripemd/ripemd160.dart'; export 'src/hash/sha/hash/digest.dart'; export 'src/hash/sha/sha256/sha256.dart'; export 'src/hash/sha/sha512/sha512.dart'; diff --git a/lib/src/bip/bip32/keys/a_bip32_public_key.dart b/lib/src/bip/bip32/keys/a_bip32_public_key.dart index a2a56b81..80493c96 100644 --- a/lib/src/bip/bip32/keys/a_bip32_public_key.dart +++ b/lib/src/bip/bip32/keys/a_bip32_public_key.dart @@ -32,7 +32,7 @@ abstract class ABip32PublicKey extends Equatable { static BigInt calcFingerprint(Uint8List publicKeyBytes) { Uint8List sha256Fingerprint = Sha256().convert(publicKeyBytes).byteList; - Uint8List ripemd160Fingerprint = Uint8List.fromList(Ripemd160().process(sha256Fingerprint)); + Uint8List ripemd160Fingerprint = Ripemd160().process(sha256Fingerprint); return BigIntUtils.decode(ripemd160Fingerprint.sublist(0, 4)); } diff --git a/lib/src/hash/keccak/keccakf1600.dart b/lib/src/hash/keccak/keccakf1600.dart index e2ee3449..8316009b 100644 --- a/lib/src/hash/keccak/keccakf1600.dart +++ b/lib/src/hash/keccak/keccakf1600.dart @@ -20,8 +20,8 @@ import 'dart:typed_data'; -import 'package:cryptography_utils/src/hash/keccak/register64/register64.dart'; -import 'package:cryptography_utils/src/hash/keccak/register64/register64_list.dart'; +import 'package:cryptography_utils/src/utils/register64/register64.dart'; +import 'package:cryptography_utils/src/utils/register64/register64_list.dart'; ///[KeccakF1600] This class is essential for processing input data through the sponge construction, ensuring proper diffusion and security /// in hash computations. It operates on a 1600-bit state, repeatedly applying a series of transformations to mix the input data and produce diff --git a/lib/src/hash/ripemd/a_md4_digest.dart b/lib/src/hash/ripemd/a_md4_digest.dart new file mode 100644 index 00000000..ba785dde --- /dev/null +++ b/lib/src/hash/ripemd/a_md4_digest.dart @@ -0,0 +1,221 @@ +// This class was primarily influenced by: +// "pointycastle" - Copyright (c) 2000 - 2019 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import 'dart:typed_data'; + +import 'package:cryptography_utils/src/utils/register64/register64.dart'; + +/// [AMD4Digest] provides message digestion, including byte processing, block management, and state updates. +/// This class can serve as a base for RIPEMD-128, RIPEMD-160, RIPEMD-256, RIPEMD-320, SM3Digest, and SHA-1, SHA-224, and SHA-256 algorithms. + +/// Algorithms already implemented using AMD4Digest: RIPEMD-160. Algorithms not yet implemented but potentially possible with this algorithm: RIPEMD-128, RIPEMD-256, RIPEMD-320, SM3Digest, SHA-1, SHA-224 and SHA-256. +abstract class AMD4Digest { + final Register64 _byteCountRegister64 = Register64(0); + final Uint8List _wordBufferUint8List = Uint8List(4); + final List _bufferList; + final List _stateList; + final Endian _endian; + final int _packedStateSize; + + final int _digestSize; + late int _wordBufferOffset; + late int _bufferOffset; + + AMD4Digest({ + required Endian endian, + required int digestSize, + required int stateSize, + required int bufferSize, + required int packedStateSize, + }) : _endian = endian, + _digestSize = digestSize, + _stateList = List.filled(stateSize, 0, growable: false), + _bufferList = List.filled(bufferSize, 0, growable: false), + _packedStateSize = packedStateSize { + _reset(); + } + + List get stateList => _stateList; + + List get bufferList => _bufferList; + + Uint8List process(Uint8List inputUint8List) { + _update(inputUint8List, 0, inputUint8List.length); + + Uint8List outputUint8List = Uint8List(_digestSize); + int length = _doFinal(outputUint8List, 0); + + return outputUint8List.sublist(0, length); + } + + void resetState(); + + void processBlock(); + + void _update(Uint8List inputUint8List, int inputOffset, int length) { + int nbytes; + int inputOffsetValue = inputOffset; + int lengthValue = length; + + nbytes = _processUntilNextWord(inputUint8List, inputOffsetValue, lengthValue); + inputOffsetValue += nbytes; + lengthValue -= nbytes; + + nbytes = _processWholeWords(inputUint8List, inputOffsetValue, lengthValue); + inputOffsetValue += nbytes; + lengthValue -= nbytes; + + _processByte(inputUint8List, inputOffsetValue, lengthValue); + } + + int _doFinal(Uint8List outputUint8List, int outputOffset) { + Register64 bitLengthRegister64 = Register64() + ..setRegister64(_byteCountRegister64) + ..shiftLeft(3); + + _processPadding(); + _processLength(bitLengthRegister64); + _finalizeBlockProcessing(); + + _packState(outputUint8List, outputOffset); + + _reset(); + + return _digestSize; + } + + void _reset() { + _byteCountRegister64.setInt(0); + + _wordBufferOffset = 0; + _wordBufferUint8List.fillRange(0, _wordBufferUint8List.length, 0); + + _bufferOffset = 0; + _bufferList.fillRange(0, _bufferList.length, 0); + + resetState(); + } + + int _processUntilNextWord(Uint8List inputUint8List, int inputOffset, int length) { + int processed = 0; + int inputOffsetValue = inputOffset; + int lengthValue = length; + + while ((_wordBufferOffset != 0) && lengthValue > 0) { + _updateByte(inputUint8List[inputOffsetValue]); + + inputOffsetValue++; + lengthValue--; + processed++; + } + return processed; + } + + int _processWholeWords(Uint8List inputUint8List, int inputOffset, int length) { + int processed = 0; + int inputOffsetValue = inputOffset; + int lengthValue = length; + + while (lengthValue > _wordBufferUint8List.length) { + _processWord(inputUint8List, inputOffsetValue); + + inputOffsetValue += _wordBufferUint8List.length; + lengthValue -= _wordBufferUint8List.length; + _byteCountRegister64.sumInt(_wordBufferUint8List.length); + processed += 4; + } + return processed; + } + + void _processByte(Uint8List inputUint8List, int inputOffset, int length) { + int inputOffsetValue = inputOffset; + int lengthValue = length; + + while (lengthValue > 0) { + _updateByte(inputUint8List[inputOffsetValue]); + + inputOffsetValue++; + lengthValue--; + } + } + + void _processPadding() { + _updateByte(128); + while (_wordBufferOffset != 0) { + _updateByte(0); + } + } + + void _updateByte(int input) { + _wordBufferUint8List[_wordBufferOffset++] = _mask8Bits(input); + _flushWordBuffer(); + _byteCountRegister64.sumInt(1); + } + + void _processLength(Register64 bitLengthRegister64) { + if (_bufferOffset > 14) { + _finalizeBlockProcessing(); + } + + _bufferList[14] = bitLengthRegister64.lowerHalf; + _bufferList[15] = bitLengthRegister64.upperHalf; + } + + void _packState(Uint8List outputUint8List, int outputOffset) { + for (int i = 0; i < _packedStateSize; i++) { + _packInput32(_stateList[i], outputUint8List, outputOffset + i * 4, _endian); + } + } + + void _flushWordBuffer() { + if (_wordBufferOffset == _wordBufferUint8List.length) { + _processWord(_wordBufferUint8List, 0); + _wordBufferOffset = 0; + } + } + + void _processWord(Uint8List inputUint8List, int inputOffset) { + _bufferList[_bufferOffset++] = _unpackInput32Bits(inputUint8List, inputOffset, _endian); + + if (_bufferOffset == 16) { + _finalizeBlockProcessing(); + } + } + + void _finalizeBlockProcessing() { + processBlock(); + + _bufferOffset = 0; + _bufferList.fillRange(0, 16, 0); + } + + int _mask8Bits(int input) { + return input & 0xFF; + } + + int _unpackInput32Bits(Uint8List inputUint8List, int offset, Endian endian) { + ByteData byteData = ByteData.view(inputUint8List.buffer, inputUint8List.offsetInBytes, inputUint8List.length); + return byteData.getUint32(offset, endian); + } + + void _packInput32(int x, Uint8List outputUint8List, int offset, Endian endian) { + ByteData.view(outputUint8List.buffer, outputUint8List.offsetInBytes, outputUint8List.length).setUint32(offset, x, endian); + } +} diff --git a/lib/src/hash/ripemd/ripemd160.dart b/lib/src/hash/ripemd/ripemd160.dart new file mode 100644 index 00000000..4edcfd79 --- /dev/null +++ b/lib/src/hash/ripemd/ripemd160.dart @@ -0,0 +1,502 @@ +// This class was primarily influenced by: +// "pointycastle" - Copyright (c) 2000 - 2019 The Legion of the Bouncy Castle Inc. (https://www.bouncycastle.org) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import 'dart:typed_data'; + +import 'package:cryptography_utils/src/hash/ripemd/a_md4_digest.dart'; +import 'package:cryptography_utils/src/utils/register64/register64.dart'; + +/// [Ripemd160] is an implementation of RIPEMD-160 algorithm which is a secure hash function +/// producing a 160-bit output, used for address encoding of Bitcoin and Cosmos. +class Ripemd160 extends AMD4Digest { + static const int _digestLength = 20; + + final Register64 register64 = Register64(); + + late int _aHash; + late int _bHash; + late int _cHash; + late int _dHash; + late int _eHash; + late int _aaHash; + late int _bbHash; + late int _ccHash; + late int _ddHash; + late int _eeHash; + + Ripemd160() + : super( + endian: Endian.little, + digestSize: _digestLength, + stateSize: 5, + bufferSize: 16, + packedStateSize: 5, + ); + + @override + void resetState() { + stateList[0] = 0x67452301; + stateList[1] = 0xefcdab89; + stateList[2] = 0x98badcfe; + stateList[3] = 0x10325476; + stateList[4] = 0xc3d2e1f0; + } + + @override + void processBlock() { + _aHash = _aaHash = stateList[0]; + _bHash = _bbHash = stateList[1]; + _cHash = _ccHash = stateList[2]; + _dHash = _ddHash = stateList[3]; + _eHash = _eeHash = stateList[4]; + + _doRounds16Left(); + _doRounds16Right(); + + _doRounds31Left(); + _doRounds31Right(); + + _doRounds47Left(); + _doRounds47Right(); + + _doRounds63Left(); + _doRounds63Right(); + + _doRounds79Left(); + _doRounds79Right(); + + _ddHash = _mask32Bits(_ddHash + _cHash + stateList[1]); + stateList[1] = _mask32Bits(stateList[2] + _dHash + _eeHash); + stateList[2] = _mask32Bits(stateList[3] + _eHash + _aaHash); + stateList[3] = _mask32Bits(stateList[4] + _aHash + _bbHash); + stateList[4] = _mask32Bits(stateList[0] + _bHash + _ccHash); + stateList[0] = _ddHash; + } + + void _doRounds16Left() { + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _handleXorCombination(_bHash, _cHash, _dHash) + bufferList[0], 11), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _handleXorCombination(_aHash, _bHash, _cHash) + bufferList[1], 14), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _handleXorCombination(_eHash, _aHash, _bHash) + bufferList[2], 15), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _handleXorCombination(_dHash, _eHash, _aHash) + bufferList[3], 12), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _handleXorCombination(_cHash, _dHash, _eHash) + bufferList[4], 5), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _handleXorCombination(_bHash, _cHash, _dHash) + bufferList[5], 8), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _handleXorCombination(_aHash, _bHash, _cHash) + bufferList[6], 7), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _handleXorCombination(_eHash, _aHash, _bHash) + bufferList[7], 9), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _handleXorCombination(_dHash, _eHash, _aHash) + bufferList[8], 11), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _handleXorCombination(_cHash, _dHash, _eHash) + bufferList[9], 13), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _handleXorCombination(_bHash, _cHash, _dHash) + bufferList[10], 14), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _handleXorCombination(_aHash, _bHash, _cHash) + bufferList[11], 15), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _handleXorCombination(_eHash, _aHash, _bHash) + bufferList[12], 6), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _handleXorCombination(_dHash, _eHash, _aHash) + bufferList[13], 7), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _handleXorCombination(_cHash, _dHash, _eHash) + bufferList[14], 9), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _handleXorCombination(_bHash, _cHash, _dHash) + bufferList[15], 8), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + } + + void _doRounds16Right() { + int roundsValue = 0x50a28be6; + _aaHash = + _doSum32Bits(_doCircularRotateLeft(_aaHash + _handleXorWithNegation(_bbHash, _ccHash, _ddHash) + bufferList[5] + roundsValue, 8), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = + _doSum32Bits(_doCircularRotateLeft(_eeHash + _handleXorWithNegation(_aaHash, _bbHash, _ccHash) + bufferList[14] + roundsValue, 9), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = + _doSum32Bits(_doCircularRotateLeft(_ddHash + _handleXorWithNegation(_eeHash, _aaHash, _bbHash) + bufferList[7] + roundsValue, 9), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = + _doSum32Bits(_doCircularRotateLeft(_ccHash + _handleXorWithNegation(_ddHash, _eeHash, _aaHash) + bufferList[0] + roundsValue, 11), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = + _doSum32Bits(_doCircularRotateLeft(_bbHash + _handleXorWithNegation(_ccHash, _ddHash, _eeHash) + bufferList[9] + roundsValue, 13), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = + _doSum32Bits(_doCircularRotateLeft(_aaHash + _handleXorWithNegation(_bbHash, _ccHash, _ddHash) + bufferList[2] + roundsValue, 15), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = + _doSum32Bits(_doCircularRotateLeft(_eeHash + _handleXorWithNegation(_aaHash, _bbHash, _ccHash) + bufferList[11] + roundsValue, 15), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = + _doSum32Bits(_doCircularRotateLeft(_ddHash + _handleXorWithNegation(_eeHash, _aaHash, _bbHash) + bufferList[4] + roundsValue, 5), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = + _doSum32Bits(_doCircularRotateLeft(_ccHash + _handleXorWithNegation(_ddHash, _eeHash, _aaHash) + bufferList[13] + roundsValue, 7), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = + _doSum32Bits(_doCircularRotateLeft(_bbHash + _handleXorWithNegation(_ccHash, _ddHash, _eeHash) + bufferList[6] + roundsValue, 7), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = + _doSum32Bits(_doCircularRotateLeft(_aaHash + _handleXorWithNegation(_bbHash, _ccHash, _ddHash) + bufferList[15] + roundsValue, 8), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = + _doSum32Bits(_doCircularRotateLeft(_eeHash + _handleXorWithNegation(_aaHash, _bbHash, _ccHash) + bufferList[8] + roundsValue, 11), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = + _doSum32Bits(_doCircularRotateLeft(_ddHash + _handleXorWithNegation(_eeHash, _aaHash, _bbHash) + bufferList[1] + roundsValue, 14), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = + _doSum32Bits(_doCircularRotateLeft(_ccHash + _handleXorWithNegation(_ddHash, _eeHash, _aaHash) + bufferList[10] + roundsValue, 14), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = + _doSum32Bits(_doCircularRotateLeft(_bbHash + _handleXorWithNegation(_ccHash, _ddHash, _eeHash) + bufferList[3] + roundsValue, 12), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = + _doSum32Bits(_doCircularRotateLeft(_aaHash + _handleXorWithNegation(_bbHash, _ccHash, _ddHash) + bufferList[12] + roundsValue, 6), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + } + + void _doRounds31Left() { + int roundsValue = 0x5a827999; + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _selectBitsByInput(_aHash, _bHash, _cHash) + bufferList[7] + roundsValue, 7), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _selectBitsByInput(_eHash, _aHash, _bHash) + bufferList[4] + roundsValue, 6), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _selectBitsByInput(_dHash, _eHash, _aHash) + bufferList[13] + roundsValue, 8), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _selectBitsByInput(_cHash, _dHash, _eHash) + bufferList[1] + roundsValue, 13), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _selectBitsByInput(_bHash, _cHash, _dHash) + bufferList[10] + roundsValue, 11), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _selectBitsByInput(_aHash, _bHash, _cHash) + bufferList[6] + roundsValue, 9), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _selectBitsByInput(_eHash, _aHash, _bHash) + bufferList[15] + roundsValue, 7), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _selectBitsByInput(_dHash, _eHash, _aHash) + bufferList[3] + roundsValue, 15), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _selectBitsByInput(_cHash, _dHash, _eHash) + bufferList[12] + roundsValue, 7), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _selectBitsByInput(_bHash, _cHash, _dHash) + bufferList[0] + roundsValue, 12), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _selectBitsByInput(_aHash, _bHash, _cHash) + bufferList[9] + roundsValue, 15), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _selectBitsByInput(_eHash, _aHash, _bHash) + bufferList[5] + roundsValue, 9), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _selectBitsByInput(_dHash, _eHash, _aHash) + bufferList[2] + roundsValue, 11), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _selectBitsByInput(_cHash, _dHash, _eHash) + bufferList[14] + roundsValue, 7), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _selectBitsByInput(_bHash, _cHash, _dHash) + bufferList[11] + roundsValue, 13), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _selectBitsByInput(_aHash, _bHash, _cHash) + bufferList[8] + roundsValue, 12), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + } + + void _doRounds31Right() { + int roundsValue = 0x5c4dd124; + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _selectBitsByValue(_aaHash, _bbHash, _ccHash) + bufferList[6] + roundsValue, 9), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = + _doSum32Bits(_doCircularRotateLeft(_ddHash + _selectBitsByValue(_eeHash, _aaHash, _bbHash) + bufferList[11] + roundsValue, 13), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = _doSum32Bits(_doCircularRotateLeft(_ccHash + _selectBitsByValue(_ddHash, _eeHash, _aaHash) + bufferList[3] + roundsValue, 15), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _selectBitsByValue(_ccHash, _ddHash, _eeHash) + bufferList[7] + roundsValue, 7), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = _doSum32Bits(_doCircularRotateLeft(_aaHash + _selectBitsByValue(_bbHash, _ccHash, _ddHash) + bufferList[0] + roundsValue, 12), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _selectBitsByValue(_aaHash, _bbHash, _ccHash) + bufferList[13] + roundsValue, 8), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = _doSum32Bits(_doCircularRotateLeft(_ddHash + _selectBitsByValue(_eeHash, _aaHash, _bbHash) + bufferList[5] + roundsValue, 9), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = + _doSum32Bits(_doCircularRotateLeft(_ccHash + _selectBitsByValue(_ddHash, _eeHash, _aaHash) + bufferList[10] + roundsValue, 11), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _selectBitsByValue(_ccHash, _ddHash, _eeHash) + bufferList[14] + roundsValue, 7), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = _doSum32Bits(_doCircularRotateLeft(_aaHash + _selectBitsByValue(_bbHash, _ccHash, _ddHash) + bufferList[15] + roundsValue, 7), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _selectBitsByValue(_aaHash, _bbHash, _ccHash) + bufferList[8] + roundsValue, 12), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = _doSum32Bits(_doCircularRotateLeft(_ddHash + _selectBitsByValue(_eeHash, _aaHash, _bbHash) + bufferList[12] + roundsValue, 7), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = _doSum32Bits(_doCircularRotateLeft(_ccHash + _selectBitsByValue(_ddHash, _eeHash, _aaHash) + bufferList[4] + roundsValue, 6), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _selectBitsByValue(_ccHash, _ddHash, _eeHash) + bufferList[9] + roundsValue, 15), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = _doSum32Bits(_doCircularRotateLeft(_aaHash + _selectBitsByValue(_bbHash, _ccHash, _ddHash) + bufferList[1] + roundsValue, 13), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _selectBitsByValue(_aaHash, _bbHash, _ccHash) + bufferList[2] + roundsValue, 11), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + } + + void _doRounds47Left() { + int roundsValue = 0x6ed9eba1; + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _handleOrAndXor(_eHash, _aHash, _bHash) + bufferList[3] + roundsValue, 11), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _handleOrAndXor(_dHash, _eHash, _aHash) + bufferList[10] + roundsValue, 13), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _handleOrAndXor(_cHash, _dHash, _eHash) + bufferList[14] + roundsValue, 6), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _handleOrAndXor(_bHash, _cHash, _dHash) + bufferList[4] + roundsValue, 7), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _handleOrAndXor(_aHash, _bHash, _cHash) + bufferList[9] + roundsValue, 14), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _handleOrAndXor(_eHash, _aHash, _bHash) + bufferList[15] + roundsValue, 9), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _handleOrAndXor(_dHash, _eHash, _aHash) + bufferList[8] + roundsValue, 13), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _handleOrAndXor(_cHash, _dHash, _eHash) + bufferList[1] + roundsValue, 15), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _handleOrAndXor(_bHash, _cHash, _dHash) + bufferList[2] + roundsValue, 14), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _handleOrAndXor(_aHash, _bHash, _cHash) + bufferList[7] + roundsValue, 8), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _handleOrAndXor(_eHash, _aHash, _bHash) + bufferList[0] + roundsValue, 13), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _handleOrAndXor(_dHash, _eHash, _aHash) + bufferList[6] + roundsValue, 6), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _handleOrAndXor(_cHash, _dHash, _eHash) + bufferList[13] + roundsValue, 5), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _handleOrAndXor(_bHash, _cHash, _dHash) + bufferList[11] + roundsValue, 12), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _handleOrAndXor(_aHash, _bHash, _cHash) + bufferList[5] + roundsValue, 7), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _handleOrAndXor(_eHash, _aHash, _bHash) + bufferList[12] + roundsValue, 5), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + } + + void _doRounds47Right() { + int roundsValue = 0x6d703ef3; + _ddHash = _doSum32Bits(_doCircularRotateLeft(_ddHash + _handleOrAndXor(_eeHash, _aaHash, _bbHash) + bufferList[15] + roundsValue, 9), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = _doSum32Bits(_doCircularRotateLeft(_ccHash + _handleOrAndXor(_ddHash, _eeHash, _aaHash) + bufferList[5] + roundsValue, 7), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _handleOrAndXor(_ccHash, _ddHash, _eeHash) + bufferList[1] + roundsValue, 15), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = _doSum32Bits(_doCircularRotateLeft(_aaHash + _handleOrAndXor(_bbHash, _ccHash, _ddHash) + bufferList[3] + roundsValue, 11), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _handleOrAndXor(_aaHash, _bbHash, _ccHash) + bufferList[7] + roundsValue, 8), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = _doSum32Bits(_doCircularRotateLeft(_ddHash + _handleOrAndXor(_eeHash, _aaHash, _bbHash) + bufferList[14] + roundsValue, 6), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = _doSum32Bits(_doCircularRotateLeft(_ccHash + _handleOrAndXor(_ddHash, _eeHash, _aaHash) + bufferList[6] + roundsValue, 6), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _handleOrAndXor(_ccHash, _ddHash, _eeHash) + bufferList[9] + roundsValue, 14), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = _doSum32Bits(_doCircularRotateLeft(_aaHash + _handleOrAndXor(_bbHash, _ccHash, _ddHash) + bufferList[11] + roundsValue, 12), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _handleOrAndXor(_aaHash, _bbHash, _ccHash) + bufferList[8] + roundsValue, 13), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = _doSum32Bits(_doCircularRotateLeft(_ddHash + _handleOrAndXor(_eeHash, _aaHash, _bbHash) + bufferList[12] + roundsValue, 5), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = _doSum32Bits(_doCircularRotateLeft(_ccHash + _handleOrAndXor(_ddHash, _eeHash, _aaHash) + bufferList[2] + roundsValue, 14), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _handleOrAndXor(_ccHash, _ddHash, _eeHash) + bufferList[10] + roundsValue, 13), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = _doSum32Bits(_doCircularRotateLeft(_aaHash + _handleOrAndXor(_bbHash, _ccHash, _ddHash) + bufferList[0] + roundsValue, 13), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _handleOrAndXor(_aaHash, _bbHash, _ccHash) + bufferList[4] + roundsValue, 7), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = _doSum32Bits(_doCircularRotateLeft(_ddHash + _handleOrAndXor(_eeHash, _aaHash, _bbHash) + bufferList[13] + roundsValue, 5), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + } + + void _doRounds63Left() { + int roundsValue = 0x8f1bbcdc; + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _selectBitsByValue(_dHash, _eHash, _aHash) + bufferList[1] + roundsValue, 11), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _selectBitsByValue(_cHash, _dHash, _eHash) + bufferList[9] + roundsValue, 12), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _selectBitsByValue(_bHash, _cHash, _dHash) + bufferList[11] + roundsValue, 14), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _selectBitsByValue(_aHash, _bHash, _cHash) + bufferList[10] + roundsValue, 15), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _selectBitsByValue(_eHash, _aHash, _bHash) + bufferList[0] + roundsValue, 14), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _selectBitsByValue(_dHash, _eHash, _aHash) + bufferList[8] + roundsValue, 15), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _selectBitsByValue(_cHash, _dHash, _eHash) + bufferList[12] + roundsValue, 9), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _selectBitsByValue(_bHash, _cHash, _dHash) + bufferList[4] + roundsValue, 8), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _selectBitsByValue(_aHash, _bHash, _cHash) + bufferList[13] + roundsValue, 9), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _selectBitsByValue(_eHash, _aHash, _bHash) + bufferList[3] + roundsValue, 14), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _selectBitsByValue(_dHash, _eHash, _aHash) + bufferList[7] + roundsValue, 5), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _selectBitsByValue(_cHash, _dHash, _eHash) + bufferList[15] + roundsValue, 6), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _selectBitsByValue(_bHash, _cHash, _dHash) + bufferList[14] + roundsValue, 8), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _selectBitsByValue(_aHash, _bHash, _cHash) + bufferList[5] + roundsValue, 6), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _selectBitsByValue(_eHash, _aHash, _bHash) + bufferList[6] + roundsValue, 5), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _selectBitsByValue(_dHash, _eHash, _aHash) + bufferList[2] + roundsValue, 12), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + } + + void _doRounds63Right() { + int roundsValue = 0x7a6d76e9; + _ccHash = _doSum32Bits(_doCircularRotateLeft(_ccHash + _selectBitsByInput(_ddHash, _eeHash, _aaHash) + bufferList[8] + roundsValue, 15), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _selectBitsByInput(_ccHash, _ddHash, _eeHash) + bufferList[6] + roundsValue, 5), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = _doSum32Bits(_doCircularRotateLeft(_aaHash + _selectBitsByInput(_bbHash, _ccHash, _ddHash) + bufferList[4] + roundsValue, 8), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _selectBitsByInput(_aaHash, _bbHash, _ccHash) + bufferList[1] + roundsValue, 11), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = _doSum32Bits(_doCircularRotateLeft(_ddHash + _selectBitsByInput(_eeHash, _aaHash, _bbHash) + bufferList[3] + roundsValue, 14), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = + _doSum32Bits(_doCircularRotateLeft(_ccHash + _selectBitsByInput(_ddHash, _eeHash, _aaHash) + bufferList[11] + roundsValue, 14), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _selectBitsByInput(_ccHash, _ddHash, _eeHash) + bufferList[15] + roundsValue, 6), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = _doSum32Bits(_doCircularRotateLeft(_aaHash + _selectBitsByInput(_bbHash, _ccHash, _ddHash) + bufferList[0] + roundsValue, 14), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _selectBitsByInput(_aaHash, _bbHash, _ccHash) + bufferList[5] + roundsValue, 6), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = _doSum32Bits(_doCircularRotateLeft(_ddHash + _selectBitsByInput(_eeHash, _aaHash, _bbHash) + bufferList[12] + roundsValue, 9), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = _doSum32Bits(_doCircularRotateLeft(_ccHash + _selectBitsByInput(_ddHash, _eeHash, _aaHash) + bufferList[2] + roundsValue, 12), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _selectBitsByInput(_ccHash, _ddHash, _eeHash) + bufferList[13] + roundsValue, 9), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = _doSum32Bits(_doCircularRotateLeft(_aaHash + _selectBitsByInput(_bbHash, _ccHash, _ddHash) + bufferList[9] + roundsValue, 12), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _selectBitsByInput(_aaHash, _bbHash, _ccHash) + bufferList[7] + roundsValue, 5), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = + _doSum32Bits(_doCircularRotateLeft(_ddHash + _selectBitsByInput(_eeHash, _aaHash, _bbHash) + bufferList[10] + roundsValue, 15), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = _doSum32Bits(_doCircularRotateLeft(_ccHash + _selectBitsByInput(_ddHash, _eeHash, _aaHash) + bufferList[14] + roundsValue, 8), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + } + + void _doRounds79Left() { + int roundsValue = 0xa953fd4e; + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _handleXorWithNegation(_cHash, _dHash, _eHash) + bufferList[4] + roundsValue, 9), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _handleXorWithNegation(_bHash, _cHash, _dHash) + bufferList[0] + roundsValue, 15), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _handleXorWithNegation(_aHash, _bHash, _cHash) + bufferList[5] + roundsValue, 5), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _handleXorWithNegation(_eHash, _aHash, _bHash) + bufferList[9] + roundsValue, 11), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _handleXorWithNegation(_dHash, _eHash, _aHash) + bufferList[7] + roundsValue, 6), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _handleXorWithNegation(_cHash, _dHash, _eHash) + bufferList[12] + roundsValue, 8), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _handleXorWithNegation(_bHash, _cHash, _dHash) + bufferList[2] + roundsValue, 13), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _handleXorWithNegation(_aHash, _bHash, _cHash) + bufferList[10] + roundsValue, 12), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _handleXorWithNegation(_eHash, _aHash, _bHash) + bufferList[14] + roundsValue, 5), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _handleXorWithNegation(_dHash, _eHash, _aHash) + bufferList[1] + roundsValue, 12), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _handleXorWithNegation(_cHash, _dHash, _eHash) + bufferList[3] + roundsValue, 13), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + _aHash = _doSum32Bits(_doCircularRotateLeft(_aHash + _handleXorWithNegation(_bHash, _cHash, _dHash) + bufferList[8] + roundsValue, 14), _eHash); + _cHash = register64.rotateLeft32Bits(_cHash, 10); + _eHash = _doSum32Bits(_doCircularRotateLeft(_eHash + _handleXorWithNegation(_aHash, _bHash, _cHash) + bufferList[11] + roundsValue, 11), _dHash); + _bHash = register64.rotateLeft32Bits(_bHash, 10); + _dHash = _doSum32Bits(_doCircularRotateLeft(_dHash + _handleXorWithNegation(_eHash, _aHash, _bHash) + bufferList[6] + roundsValue, 8), _cHash); + _aHash = register64.rotateLeft32Bits(_aHash, 10); + _cHash = _doSum32Bits(_doCircularRotateLeft(_cHash + _handleXorWithNegation(_dHash, _eHash, _aHash) + bufferList[15] + roundsValue, 5), _bHash); + _eHash = register64.rotateLeft32Bits(_eHash, 10); + _bHash = _doSum32Bits(_doCircularRotateLeft(_bHash + _handleXorWithNegation(_cHash, _dHash, _eHash) + bufferList[13] + roundsValue, 6), _aHash); + _dHash = register64.rotateLeft32Bits(_dHash, 10); + } + + void _doRounds79Right() { + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _handleXorCombination(_ccHash, _ddHash, _eeHash) + bufferList[12], 8), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = _doSum32Bits(_doCircularRotateLeft(_aaHash + _handleXorCombination(_bbHash, _ccHash, _ddHash) + bufferList[15], 5), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _handleXorCombination(_aaHash, _bbHash, _ccHash) + bufferList[10], 12), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = _doSum32Bits(_doCircularRotateLeft(_ddHash + _handleXorCombination(_eeHash, _aaHash, _bbHash) + bufferList[4], 9), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = _doSum32Bits(_doCircularRotateLeft(_ccHash + _handleXorCombination(_ddHash, _eeHash, _aaHash) + bufferList[1], 12), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _handleXorCombination(_ccHash, _ddHash, _eeHash) + bufferList[5], 5), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = _doSum32Bits(_doCircularRotateLeft(_aaHash + _handleXorCombination(_bbHash, _ccHash, _ddHash) + bufferList[8], 14), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _handleXorCombination(_aaHash, _bbHash, _ccHash) + bufferList[7], 6), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = _doSum32Bits(_doCircularRotateLeft(_ddHash + _handleXorCombination(_eeHash, _aaHash, _bbHash) + bufferList[6], 8), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = _doSum32Bits(_doCircularRotateLeft(_ccHash + _handleXorCombination(_ddHash, _eeHash, _aaHash) + bufferList[2], 13), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _handleXorCombination(_ccHash, _ddHash, _eeHash) + bufferList[13], 6), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + _aaHash = _doSum32Bits(_doCircularRotateLeft(_aaHash + _handleXorCombination(_bbHash, _ccHash, _ddHash) + bufferList[14], 5), _eeHash); + _ccHash = register64.rotateLeft32Bits(_ccHash, 10); + _eeHash = _doSum32Bits(_doCircularRotateLeft(_eeHash + _handleXorCombination(_aaHash, _bbHash, _ccHash) + bufferList[0], 15), _ddHash); + _bbHash = register64.rotateLeft32Bits(_bbHash, 10); + _ddHash = _doSum32Bits(_doCircularRotateLeft(_ddHash + _handleXorCombination(_eeHash, _aaHash, _bbHash) + bufferList[3], 13), _ccHash); + _aaHash = register64.rotateLeft32Bits(_aaHash, 10); + _ccHash = _doSum32Bits(_doCircularRotateLeft(_ccHash + _handleXorCombination(_ddHash, _eeHash, _aaHash) + bufferList[9], 11), _bbHash); + _eeHash = register64.rotateLeft32Bits(_eeHash, 10); + _bbHash = _doSum32Bits(_doCircularRotateLeft(_bbHash + _handleXorCombination(_ccHash, _ddHash, _eeHash) + bufferList[11], 11), _aaHash); + _ddHash = register64.rotateLeft32Bits(_ddHash, 10); + } + + int _handleXorCombination(int input, int offset, int value) { + return input ^ offset ^ value; + } + + int _selectBitsByInput(int input, int offset, int value) { + return (input & offset) | (~input & value); + } + + int _handleOrAndXor(int input, int offset, int value) { + return (input | ~offset) ^ value; + } + + int _selectBitsByValue(int input, int offset, int value) { + return (input & value) | (offset & ~value); + } + + int _handleXorWithNegation(int input, int offset, int value) { + return input ^ (offset | ~value); + } + + int _mask32Bits(int input) { + return input & 0xFFFFFFFF; + } + + int _doCircularRotateLeft(int chunk32Bits, int offset) { + return register64.rotateLeft32Bits(_mask32Bits(chunk32Bits), offset); + } + + int _doSum32Bits(int chunk32Bits, int output) { + return (chunk32Bits + output) & 0xFFFFFFFF; + } +} diff --git a/lib/src/hash/ripemd160.dart b/lib/src/hash/ripemd160.dart deleted file mode 100644 index e40cc2c7..00000000 --- a/lib/src/hash/ripemd160.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'dart:typed_data'; - -import 'package:pointycastle/digests/ripemd160.dart'; - -/// [Ripemd160] is an implementation of RIPEMD-160 algorithm which is a secure hash function -/// producing a 160-bit output, used for secure data processing and digital signatures. -class Ripemd160 { - Uint8List process(Uint8List data) { - // TODO(dominik): Implement custom version of RIPEMD16 hashing. - return RIPEMD160Digest().process(data); - } -} diff --git a/lib/src/hash/sha/sha256/sha256.dart b/lib/src/hash/sha/sha256/sha256.dart index 1006e333..1a7893f1 100644 --- a/lib/src/hash/sha/sha256/sha256.dart +++ b/lib/src/hash/sha/sha256/sha256.dart @@ -33,6 +33,7 @@ import 'package:cryptography_utils/src/hash/sha/hash/digest.dart'; import 'package:cryptography_utils/src/hash/sha/sha256/sha256_sink.dart'; /// [Sha256] is a singleton implementation of the SHA-256 hashing algorithm - defines the block size. +/// This class, with its implementation of the SHA-256 algorithm, is not compatible with the AMD4Digest class. class Sha256 extends AHash { static const int _bytesPerWord = 4; static final Sha256 _sha256 = Sha256._(); diff --git a/lib/src/hash/keccak/register64/register64.dart b/lib/src/utils/register64/register64.dart similarity index 90% rename from lib/src/hash/keccak/register64/register64.dart rename to lib/src/utils/register64/register64.dart index 90f70631..d7034d66 100644 --- a/lib/src/hash/keccak/register64/register64.dart +++ b/lib/src/utils/register64/register64.dart @@ -74,16 +74,6 @@ class Register64 with EquatableMixin { int get upperHalf => _upperHalf; - void setInt(int initialValue, [int? lower32Bits]) { - if (lower32Bits != null) { - _upperHalf = initialValue; - _lowerHalf = lower32Bits; - } else { - _upperHalf = 0; - _lowerHalf = initialValue; - } - } - void setRegister64(Register64 initialRegister64) { _upperHalf = initialRegister64._upperHalf; _lowerHalf = initialRegister64._lowerHalf; @@ -109,6 +99,21 @@ class Register64 with EquatableMixin { _lowerHalf ^= otherRegister64._lowerHalf; } + int rotateLeft32Bits(int chunk32Bits, int offset) { + int maskedOffset = offset & _mask5Bits; + return _shiftLeft32Bits(chunk32Bits, maskedOffset) | (chunk32Bits >> (32 - maskedOffset)); + } + + void setInt(int initialValue, [int? lower32Bits]) { + if (lower32Bits != null) { + _upperHalf = initialValue; + _lowerHalf = lower32Bits; + } else { + _upperHalf = 0; + _lowerHalf = initialValue; + } + } + void shiftLeft(int shiftValue) { int maskedN = shiftValue & _mask6Bits; if (maskedN == 0) { @@ -137,6 +142,16 @@ class Register64 with EquatableMixin { } } + void sumInt(int chunk32Bits) { + int maskedChunk32Bits = chunk32Bits & _mask32Bits; + int sumLowerHalf = _lowerHalf + maskedChunk32Bits; + _lowerHalf = sumLowerHalf & _mask32Bits; + if (sumLowerHalf != _lowerHalf) { + _upperHalf++; + _upperHalf &= _mask32Bits; + } + } + int _shiftLeft32Bits(int chunk32Bits, int shiftValue) { int maskedN = shiftValue & _mask5Bits; int maskedX = chunk32Bits & _mask32BitsList[maskedN]; diff --git a/lib/src/hash/keccak/register64/register64_list.dart b/lib/src/utils/register64/register64_list.dart similarity index 96% rename from lib/src/hash/keccak/register64/register64_list.dart rename to lib/src/utils/register64/register64_list.dart index 9f96c2b4..4fb86aff 100644 --- a/lib/src/hash/keccak/register64/register64_list.dart +++ b/lib/src/utils/register64/register64_list.dart @@ -20,7 +20,7 @@ import 'dart:core'; -import 'package:cryptography_utils/src/hash/keccak/register64/register64.dart'; +import 'package:cryptography_utils/src/utils/register64/register64.dart'; import 'package:equatable/equatable.dart'; /// [Register64List] manages a list of 64-bit registers for the algorithm's internal state. diff --git a/pubspec.yaml b/pubspec.yaml index 226a99e7..6ed118ab 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: cryptography_utils description: "Dart package containing utility methods for common cryptographic and blockchain-specific operations" publish_to: none -version: 0.0.22 +version: 0.0.23 environment: sdk: ">=3.2.6" @@ -11,10 +11,6 @@ dependencies: # https://pub.dev/packages/equatable equatable: 2.0.5 - # A Dart library implementing cryptographic algorithms and primitives, modeled on the BouncyCastle library. - # https://pub.dev/packages/pointycastle - pointycastle: 3.9.1 - # Flutter's compute function made available for all non-Flutter Dart programs # https://pub.dev/packages/compute compute: 1.0.2 diff --git a/test/hash/ripemd/ripemd160_test.dart b/test/hash/ripemd/ripemd160_test.dart new file mode 100644 index 00000000..c64fc55c --- /dev/null +++ b/test/hash/ripemd/ripemd160_test.dart @@ -0,0 +1,48 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:cryptography_utils/cryptography_utils.dart'; +import 'package:test/test.dart'; + +void main() { + Uint8List actualDataToHash = Uint8List.fromList('123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~'.codeUnits); + + group('Tests of Ripemd160.process()', () { + test('Should [return Ripemd160 HASH] constructed from given data', () { + // Act + Uint8List actualRipemd160Result = Ripemd160().process(actualDataToHash); + + // Assert + Uint8List expectedRipemd160Result = base64Decode('iJS43Wf/c7ZqtImU2HYR0laE3q4='); + + expect(actualRipemd160Result, expectedRipemd160Result); + }); + }); + + group('Tests of Ripemd160.resetState()', () { + test('Should [return stateList] when resetState() is called', () { + // Act + Ripemd160 ripemd160 = Ripemd160()..resetState(); + List actualStateList = ripemd160.stateList; + + // Assert + List expectedStateList = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0]; + + expect(actualStateList, expectedStateList); + }); + }); + + group('Tests of Ripemd160.processBlock()', () { + test('Should [return stateList] when processBlock() is called', () { + // Act + Ripemd160 ripemd160 = Ripemd160(); + ripemd160.bufferList.setAll(0, List.generate(16, (int i) => i)); + ripemd160.processBlock(); + List actualStateList = ripemd160.stateList; + + // Assert + List expectedStateList = [0xADDECDB1, 0x583CD1D3, 0x14BA1875, 0x9759865C, 0x392A0539]; + expect(actualStateList, expectedStateList); + }); + }); +} diff --git a/test/hash/ripemd160_test.dart b/test/hash/ripemd160_test.dart deleted file mode 100644 index 45a71820..00000000 --- a/test/hash/ripemd160_test.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'dart:convert'; -import 'dart:typed_data'; - -import 'package:cryptography_utils/cryptography_utils.dart'; -import 'package:test/test.dart'; - -void main() { - Uint8List actualDataToHash = Uint8List.fromList('123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~'.codeUnits); - - group('Tests of Ripemd160.process()', () { - test('Should [return Ripemd160 HASH] constructed from given data', () { - // Act - Uint8List actualRipemd160Result = Ripemd160().process(actualDataToHash); - - // Assert - Uint8List expectedRipemd160Result = base64Decode('iJS43Wf/c7ZqtImU2HYR0laE3q4='); - - expect(actualRipemd160Result, expectedRipemd160Result); - }); - }); -} diff --git a/test/hash/keccak/register64/register64_list_test.dart b/test/utils/register64/register64_list_test.dart similarity index 95% rename from test/hash/keccak/register64/register64_list_test.dart rename to test/utils/register64/register64_list_test.dart index 451c12f7..a57b8830 100644 --- a/test/hash/keccak/register64/register64_list_test.dart +++ b/test/utils/register64/register64_list_test.dart @@ -1,4 +1,4 @@ -import 'package:cryptography_utils/src/hash/keccak/register64/register64_list.dart'; +import 'package:cryptography_utils/src/utils/register64/register64_list.dart'; import 'package:test/expect.dart'; import 'package:test/scaffolding.dart'; diff --git a/test/hash/keccak/register64/register64_test.dart b/test/utils/register64/register64_test.dart similarity index 76% rename from test/hash/keccak/register64/register64_test.dart rename to test/utils/register64/register64_test.dart index 66693eb0..2e442c17 100644 --- a/test/hash/keccak/register64/register64_test.dart +++ b/test/utils/register64/register64_test.dart @@ -1,4 +1,4 @@ -import 'package:cryptography_utils/src/hash/keccak/register64/register64.dart'; +import 'package:cryptography_utils/src/utils/register64/register64.dart'; import 'package:test/expect.dart'; import 'package:test/scaffolding.dart'; @@ -245,4 +245,81 @@ void main() { expect(actualLowerValue, expectedLowerValue); }); }); + + group('Tests for Register64.rotateLeft32Bits()', () { + test('Should [return value] when rotateLeft32Bits() is called and offset is equal to 0', () { + // Arrange + Register64 actualRegister64 = Register64(0x00000000, 0x12345678); + + // Act + int actualValue = actualRegister64.rotateLeft32Bits(actualRegister64.lowerHalf, 0); + + // Assert + int expectedValue = 0x12345678; + + expect(actualValue, expectedValue); + }); + + test('Should [return value] when rotateLeft32Bits() is called and offset is different than 0', () { + // Arrange + Register64 actualRegister64 = Register64(0x00000000, 0x12345678); + + // Act + int actualValue = actualRegister64.rotateLeft32Bits(actualRegister64.lowerHalf, 40); + + // Assert + int expectedValue = 0x34567812; + + expect(actualValue, expectedValue); + }); + }); + group('Tests for Register64.sumInt()', () { + test('Should [return lowerHalf] when sumInt() is called and Chunk32Bits is equal to 0', () { + // Arrange + Register64 actualRegister64 = Register64(0x00000001, 0x00000001); + int actualChunk32Bits = 0x00000000; + + // Act + actualRegister64.sumInt(actualChunk32Bits); + int actualLowerValue = actualRegister64.lowerHalf; + + // Assert + int expectedLowerValue = 0x00000001; + + expect(actualLowerValue, expectedLowerValue); + }); + + test('Should [return lowerHalf] when sumInt() is called and Chunk32Bits is different than 0', () { + // Arrange + Register64 actualRegister64 = Register64(0x00000001, 0x00000001); + int actualChunk32Bits = 0x00000002; + + // Act + actualRegister64.sumInt(actualChunk32Bits); + int actualLowerValue = actualRegister64.lowerHalf; + + // Assert + int expectedLowerValue = 0x00000003; + + expect(actualLowerValue, expectedLowerValue); + }); + + test('Should [return reset both half] when both half are overflow', () { + // Arrange + Register64 actualRegister64 = Register64(0xFFFFFFFF, 0xFFFFFFFF); + int chunk32Bits = 0x00000001; + + // Act + actualRegister64.sumInt(chunk32Bits); + int actualLowerValue = actualRegister64.lowerHalf; + int actualUpperValue = actualRegister64.upperHalf; + + // Assert + int expectedLowerValue = 0x00000000; + int expectedUpperValue = 0x00000000; + + expect(actualLowerValue, expectedLowerValue); + expect(actualUpperValue, expectedUpperValue); + }); + }); }