packages feed

SecureHash-SHA3 (empty) → 0.1.0.0

raw patch · 7 files changed

+604/−0 lines, 7 filesdep +basedep +bytestringsetup-changed

Dependencies added: base, bytestring

Files

+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for SecureHash-SHA3++## 0.1.0.0 -- YYYY-mm-dd++* First version. Released on an unsuspecting world.
+ LICENSE view
@@ -0,0 +1,26 @@+Copyright (c) 2018, Carter Tazio Schonwald+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the+   distribution.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ SecureHash-SHA3.cabal view
@@ -0,0 +1,79 @@+cabal-version:       2.2+-- Initial SecureHash-SHA3.cabal generated by cabal init.  For further+-- documentation, see http://haskell.org/cabal/users-guide/++-- The name of the package.+name:                SecureHash-SHA3++-- The package version.  See the Haskell package versioning policy (PVP)+-- for standards guiding when and how versions should be incremented.+-- https://wiki.haskell.org/Package_versioning_policy+-- PVP summary:      +-+------- breaking API changes+--                   | | +----- non-breaking API additions+--                   | | | +--- code changes with no API change+version:             0.1.0.0++-- A short (one-line) description of the package.+synopsis:            simple static linked SHA3 using private symbols and the ref impl++-- A longer description of the package.+description: a self contained and linker friendly one stop shop for SHA3 kit based on the keccak reference impls++-- URL for the project homepage or repository.+homepage:            https://github.com/cartazio/securehash-sha3++-- The license under which the package is released.+license:             BSD-2-Clause++-- The file containing the license text.+license-file:        LICENSE++-- The package author(s).+author:              Carter Tazio Schonwald++-- An email address to which users can send suggestions, bug reports, and+-- patches.+maintainer:          carter at wellposed dot com++-- A copyright notice.+-- copyright:++category:            System++build-type:          Simple++-- Extra files to be distributed with the package, such as examples or a+-- README.+extra-source-files: CHANGELOG.md+                    cbits/CTS_SHA3.h++-- Constraint on the version of Cabal needed to build this package.++++library+  -- Modules exported by the library.+  exposed-modules:    Crypto.SecureHash.SHA3+                      , Crypto.SecureHash.SHA3.FFI++  -- Modules included in this library but not exported.+  -- other-modules:++  -- LANGUAGE extensions used by modules in this package.+  -- other-extensions:++  -- Other library packages from which modules are imported.+  build-depends:      base >=4.3 && <4.13+                      ,bytestring >= 0.9 && < 0.11++  -- Directories containing source files.+  hs-source-dirs:      src++  -- Base language which the package is written in.+  default-language:    Haskell2010+  ghc-options:       -Wall -O2+  cc-options:        -Wall -O3+  include-dirs:      cbits+++
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ cbits/CTS_SHA3.h view
@@ -0,0 +1,349 @@+#ifndef HS_SECUREHASH_SHA3_H+#define HS_SECUREHASH_SHA3_H++/*+Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen,+Michaël Peeters, Gilles Van Assche and Ronny Van Keer,+hereby denoted as "the implementer".++For more information, feedback or questions, please refer to our website:+https://keccak.team/++To the extent possible under law, the implementer has waived all copyright+and related or neighboring rights to the source code in this file.+http://creativecommons.org/publicdomain/zero/1.0/+*/++/*+================================================================+The purpose of this source file is to demonstrate a readable and compact+implementation of all the Keccak instances approved in the FIPS 202 standard,+including the hash functions and the extendable-output functions (XOFs).++We focused on clarity and on source-code compactness,+rather than on the performance.++The advantages of this implementation are:+    + The source code is compact, after removing the comments, that is. :-)+    + There are no tables with arbitrary constants.+    + For clarity, the comments link the operations to the specifications using+        the same notation as much as possible.+    + There is no restriction in cryptographic features. In particular,+        the SHAKE128 and SHAKE256 XOFs can produce any output length.+    + The code does not use much RAM, as all operations are done in place.++The drawbacks of this implementation are:+    - There is no message queue. The whole message must be ready in a buffer.+    - It is not optimized for performance.++The implementation is even simpler on a little endian platform. Just define the+LITTLE_ENDIAN symbol in that case.++For a more complete set of implementations, please refer to+the Keccak Code Package at https://github.com/XKCP/XKCP++For more information, please refer to:+    * [Keccak Reference] https://keccak.team/files/Keccak-reference-3.0.pdf+    * [Keccak Specifications Summary] https://keccak.team/keccak_specs_summary.html++This file uses UTF-8 encoding, as some comments use Greek letters.+================================================================+*/++/**+  * Function to compute the Keccak[r, c] sponge function over a given input.+  * @param  rate            The value of the rate r.+  * @param  capacity        The value of the capacity c.+  * @param  input           Pointer to the input message.+  * @param  inputByteLen    The number of input bytes provided in the input message.+  * @param  delimitedSuffix Bits that will be automatically appended to the end+  *                         of the input message, as in domain separation.+  *                         This is a byte containing from 0 to 7 bits+  *                         These <i>n</i> bits must be in the least significant bit positions+  *                         and must be delimited with a bit 1 at position <i>n</i>+  *                         (counting from 0=LSB to 7=MSB) and followed by bits 0+  *                         from position <i>n</i>+1 to position 7.+  *                         Some examples:+  *                             - If no bits are to be appended, then @a delimitedSuffix must be 0x01.+  *                             - If the 2-bit sequence 0,1 is to be appended (as for SHA3-*), @a delimitedSuffix must be 0x06.+  *                             - If the 4-bit sequence 1,1,1,1 is to be appended (as for SHAKE*), @a delimitedSuffix must be 0x1F.+  *                             - If the 7-bit sequence 1,1,0,1,0,0,0 is to be absorbed, @a delimitedSuffix must be 0x8B.+  * @param  output          Pointer to the buffer where to store the output.+  * @param  outputByteLen   The number of output bytes desired.+  * @pre    One must have r+c=1600 and the rate a multiple of 8 bits in this implementation.+  */+static void CTS_Keccak(unsigned int rate, unsigned int capacity, const unsigned char *input, unsigned long long int inputByteLen, unsigned char delimitedSuffix, unsigned char *output, unsigned long long int outputByteLen);++/**+  *  Function to compute SHAKE128 on the input message with any output length.+  */+static void CTS_FIPS202_SHAKE128(const unsigned char *input, unsigned int inputByteLen, unsigned char *output, int outputByteLen)+{+    CTS_Keccak(1344, 256, input, inputByteLen, 0x1F, output, outputByteLen);+}++/**+  *  Function to compute SHAKE256 on the input message with any output length.+  */+static void CTS_FIPS202_SHAKE256(const unsigned char *input, unsigned int inputByteLen, unsigned char *output, int outputByteLen)+{+    CTS_Keccak(1088, 512, input, inputByteLen, 0x1F, output, outputByteLen);+}++/**+  *  Function to compute SHA3-224 on the input message. The output length is fixed to 28 bytes.+  */+static void CTS_FIPS202_SHA3_224(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)+{+    CTS_Keccak(1152, 448, input, inputByteLen, 0x06, output, 28);+}++/**+  *  Function to compute SHA3-256 on the input message. The output length is fixed to 32 bytes.+  */+static void CTS_FIPS202_SHA3_256(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)+{+    CTS_Keccak(1088, 512, input, inputByteLen, 0x06, output, 32);+}++/**+  *  Function to compute SHA3-384 on the input message. The output length is fixed to 48 bytes.+  */+static void CTS_FIPS202_SHA3_384(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)+{+    CTS_Keccak(832, 768, input, inputByteLen, 0x06, output, 48);+}++++/**+  *  Function to compute SHA3-512 on the input message. The output length is fixed to 64 bytes.+  */+static void CTS_FIPS202_SHA3_512(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)+{+    CTS_Keccak(576, 1024, input, inputByteLen, 0x06, output, 64);+}++++/*+================================================================+Technicalities+================================================================+*/++typedef unsigned char UINT8;+typedef unsigned long long int UINT64;+typedef UINT64 tKeccakLane;++#ifndef LITTLE_ENDIAN+/** Function to load a 64-bit value using the little-endian (LE) convention.+  * On a LE platform, this could be greatly simplified using a cast.+  */+static inline UINT64 CTS_load64(const UINT8 *x)+{+    int i;+    UINT64 u=0;++    for(i=7; i>=0; --i) {+        u <<= 8;+        u |= x[i];+    }+    return u;+}++/** Function to store a 64-bit value using the little-endian (LE) convention.+  * On a LE platform, this could be greatly simplified using a cast.+  */+static inline void CTS_store64(UINT8 *x, UINT64 u)+{+    unsigned int i;++    for(i=0; i<8; ++i) {+        x[i] = u;+        u >>= 8;+    }+}++/** Function to XOR into a 64-bit value using the little-endian (LE) convention.+  * On a LE platform, this could be greatly simplified using a cast.+  */+static inline void CTS_xor64(UINT8 *x, UINT64 u)+{+    unsigned int i;++    for(i=0; i<8; ++i) {+        x[i] ^= u;+        u >>= 8;+    }+}+#endif++/*+================================================================+A readable and compact implementation of the Keccak-f[1600] permutation.+================================================================+*/++#define ROL64(a, offset) ((((UINT64)a) << offset) ^ (((UINT64)a) >> (64-offset)))+#define i(x, y) ((x)+5*(y))++// This test works on GCC and CLANG, which is good enough for me+#if defined(__LITTLE_ENDIAN__) && !defined(LITTLE_ENDIAN)+#define LITTLE_ENDIAN+#endif++#if !(defined(__LITTLE_ENDIAN__) || defined(__BIG_ENDIAN__))+#error "This C code currently assumes a CLANG / GCC compatible cpp env"+#endif++#ifdef LITTLE_ENDIAN+    #define readLane(x, y)          (((tKeccakLane*)state)[i(x, y)])+    #define writeLane(x, y, lane)   (((tKeccakLane*)state)[i(x, y)]) = (lane)+    #define XORLane(x, y, lane)     (((tKeccakLane*)state)[i(x, y)]) ^= (lane)+#else+    #define readLane(x, y)          CTS_load64((UINT8*)state+sizeof(tKeccakLane)*i(x, y))+    #define writeLane(x, y, lane)   CTS_store64((UINT8*)state+sizeof(tKeccakLane)*i(x, y), lane)+    #define XORLane(x, y, lane)     CTS_xor64((UINT8*)state+sizeof(tKeccakLane)*i(x, y), lane)+#endif++/**+  * Function that computes the linear feedback shift register (LFSR) used to+  * define the round constants (see [Keccak Reference, Section 1.2]).+  */+static inline int CTS_LFSR86540(UINT8 *LFSR)+{+    int result = ((*LFSR) & 0x01) != 0;+    if (((*LFSR) & 0x80) != 0)+        /* Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1 */+        (*LFSR) = ((*LFSR) << 1) ^ 0x71;+    else+        (*LFSR) <<= 1;+    return result;+}++/**+ * Function that computes the Keccak-f[1600] permutation on the given state.+ */+static void CTS_KeccakF1600_StatePermute(void *state)+{+    unsigned int round, x, y, j, t;+    UINT8 LFSRstate = 0x01;++    for(round=0; round<24; round++) {+        {   /* === θ step (see [Keccak Reference, Section 2.3.2]) === */+            tKeccakLane C[5], D;++            /* Compute the parity of the columns */+            for(x=0; x<5; x++)+                C[x] = readLane(x, 0) ^ readLane(x, 1) ^ readLane(x, 2) ^ readLane(x, 3) ^ readLane(x, 4);+            for(x=0; x<5; x++) {+                /* Compute the θ effect for a given column */+                D = C[(x+4)%5] ^ ROL64(C[(x+1)%5], 1);+                /* Add the θ effect to the whole column */+                for (y=0; y<5; y++)+                    XORLane(x, y, D);+            }+        }++        {   /* === ρ and π steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4]) === */+            tKeccakLane current, temp;+            /* Start at coordinates (1 0) */+            x = 1; y = 0;+            current = readLane(x, y);+            /* Iterate over ((0 1)(2 3))^t * (1 0) for 0 ≤ t ≤ 23 */+            for(t=0; t<24; t++) {+                /* Compute the rotation constant r = (t+1)(t+2)/2 */+                unsigned int r = ((t+1)*(t+2)/2)%64;+                /* Compute ((0 1)(2 3)) * (x y) */+                unsigned int Y = (2*x+3*y)%5; x = y; y = Y;+                /* Swap current and state(x,y), and rotate */+                temp = readLane(x, y);+                writeLane(x, y, ROL64(current, r));+                current = temp;+            }+        }++        {   /* === χ step (see [Keccak Reference, Section 2.3.1]) === */+            tKeccakLane temp[5];+            for(y=0; y<5; y++) {+                /* Take a copy of the plane */+                for(x=0; x<5; x++)+                    temp[x] = readLane(x, y);+                /* Compute χ on the plane */+                for(x=0; x<5; x++)+                    writeLane(x, y, temp[x] ^((~temp[(x+1)%5]) & temp[(x+2)%5]));+            }+        }++        {   /* === ι step (see [Keccak Reference, Section 2.3.5]) === */+            for(j=0; j<7; j++) {+                unsigned int bitPosition = (1<<j)-1; /* 2^j-1 */+                if (CTS_LFSR86540(&LFSRstate))+                    XORLane(0, 0, (tKeccakLane)1<<bitPosition);+            }+        }+    }+}++/*+================================================================+A readable and compact implementation of the Keccak sponge functions+that use the Keccak-f[1600] permutation.+================================================================+*/++#include <string.h>+#define MIN(a, b) ((a) < (b) ? (a) : (b))++static void CTS_Keccak(unsigned int rate, unsigned int capacity, const unsigned char *input, unsigned long long int inputByteLen, unsigned char delimitedSuffix, unsigned char *output, unsigned long long int outputByteLen)+{+    UINT8 state[200];+    unsigned int rateInBytes = rate/8;+    unsigned int blockSize = 0;+    unsigned int i;++    if (((rate + capacity) != 1600) || ((rate % 8) != 0))+        return;++    /* === Initialize the state === */+    memset(state, 0, sizeof(state));++    /* === Absorb all the input blocks === */+    while(inputByteLen > 0) {+        blockSize = MIN(inputByteLen, rateInBytes);+        for(i=0; i<blockSize; i++)+            state[i] ^= input[i];+        input += blockSize;+        inputByteLen -= blockSize;++        if (blockSize == rateInBytes) {+            CTS_KeccakF1600_StatePermute(state);+            blockSize = 0;+        }+    }++    /* === Do the padding and switch to the squeezing phase === */+    /* Absorb the last few bits and add the first bit of padding (which coincides with the delimiter in delimitedSuffix) */+    state[blockSize] ^= delimitedSuffix;+    /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */+    if (((delimitedSuffix & 0x80) != 0) && (blockSize == (rateInBytes-1)))+        CTS_KeccakF1600_StatePermute(state);+    /* Add the second bit of padding */+    state[rateInBytes-1] ^= 0x80;+    /* Switch to the squeezing phase */+   CTS_KeccakF1600_StatePermute(state);++    /* === Squeeze out all the output blocks === */+    while(outputByteLen > 0) {+        blockSize = MIN(outputByteLen, rateInBytes);+        memcpy(output, state, blockSize);+        output += blockSize;+        outputByteLen -= blockSize;++        if (outputByteLen > 0)+            CTS_KeccakF1600_StatePermute(state);+    }+}++#endif
+ src/Crypto/SecureHash/SHA3.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE Trustworthy  #-}+module Crypto.SecureHash.SHA3(sha3_512) where++import Crypto.SecureHash.SHA3.FFI+import qualified Data.ByteString as BS+import Data.ByteString (ByteString)+++import Foreign.ForeignPtr       ( withForeignPtr)+import Data.ByteString.Internal (create, toForeignPtr)+import System.IO.Unsafe (unsafeDupablePerformIO)++import Foreign.Ptr+import Data.Word (Word8,Word32)++++{-# INLINE withByteStringPtr #-}+withByteStringPtr :: ByteString -> Word32 -> (Ptr Word8  -> Word32 ->  Ptr Word8-> IO ()) -> IO ByteString+withByteStringPtr b resSize f =+    withForeignPtr fptr $ \ptr ->+          create (fromIntegral resSize) $ \resPtr -> f (ptr `plusPtr` off) (fromIntegral $ BS.length b) resPtr+    where (fptr, off, _) = toForeignPtr b++unsafeDoIO :: IO a -> a+unsafeDoIO = unsafeDupablePerformIO++sha3_512_IO :: BS.ByteString -> IO ByteString+sha3_512_IO bsIn = withByteStringPtr bsIn  64 c_FIPS202_SHA3_512+++sha3_512 :: BS.ByteString ->  ByteString+sha3_512 = (\x -> unsafeDoIO (sha3_512_IO x))++c_FIPS202_SHA3_512 :: Ptr Word8 -> Word32 -> Ptr Word8 -> IO ()+c_FIPS202_SHA3_512 ptrIn size ptrOut =+    if size >= 1024+      then c_safe_FIPS202_SHA3_512 ptrIn size ptrOut+      else c_unsafe_FIPS202_SHA3_512 ptrIn size ptrOut+
+ src/Crypto/SecureHash/SHA3/FFI.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE CApiFFI #-}+{-# LANGUAGE Unsafe  #-}++-- Ugly hack to workaround https://ghc.haskell.org/trac/ghc/ticket/14452+{-# OPTIONS_GHC -O0+                -fdo-lambda-eta-expansion+                -fcase-merge+                -fstrictness+                -fno-omit-interface-pragmas+                -fno-ignore-interface-pragmas #-}++{-# OPTIONS_GHC -optc-Wall -optc-O3 #-}++++module Crypto.SecureHash.SHA3.FFI where++import Foreign.C.Types+import Foreign.Ptr+import Data.Word++{-++/* *+  *  Function to compute SHA3-512 on the input message. The output length is fixed to 64 bytes.+  */+void CTS_FIPS202_SHA3_512(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)+{+    CTS_Keccak(576, 1024, input, inputByteLen, 0x06, output, 64);+}+++-}+++{- NOTE: CUChar or Word8 would be more precise, but I'm giving them type CCHar++-}+foreign import capi unsafe "CTS_SHA3.h CTS_FIPS202_SHA3_512"+  c_unsafe_FIPS202_SHA3_512 :: Ptr Word8 -> Word32 -> Ptr Word8 -> IO ()+foreign import capi safe "CTS_SHA3.h CTS_FIPS202_SHA3_512"+  c_safe_FIPS202_SHA3_512 :: Ptr Word8 -> Word32 -> Ptr Word8 -> IO ()++foreign import capi unsafe "CTS_SHA3.h CTS_FIPS202_SHA3_256"+  c_unsafe_FIPS202_SHA3_256 :: Ptr Word8 -> CUInt -> Ptr Word8 -> IO ()+foreign import capi safe "CTS_SHA3.h CTS_FIPS202_SHA3_256"+  c_safe_FIPS202_SHA3_256 :: Ptr Word8 -> CUInt -> Ptr Word8 -> IO ()++foreign import capi unsafe "CTS_SHA3.h CTS_FIPS202_SHA3_224"+  c_unsafe_FIPS202_SHA3_224 :: Ptr Word8 -> CUInt -> Ptr Word8 -> IO ()+foreign import capi safe "CTS_SHA3.h CTS_FIPS202_SHA3_224"+  c_safe_FIPS202_SHA3_224 :: Ptr Word8 -> CUInt -> Ptr Word8 -> IO ()+++foreign import capi unsafe "CTS_SHA3.h CTS_FIPS202_SHA3_384"+  c_unsafe_FIPS202_SHA3_384 :: Ptr Word8 -> CUInt -> Ptr Word8 -> IO ()+foreign import capi safe "CTS_SHA3.h CTS_FIPS202_SHA3_384"+  c_safe_FIPS202_SHA3_384 :: Ptr Word8 -> CUInt -> Ptr Word8 -> IO ()+++foreign import capi unsafe "CTS_SHA3.h CTS_FIPS202_SHAKE128"+  c_unsafe_FIPS202_SHAKE128 :: Ptr Word8 -> CUInt -> Ptr Word8 -> CUInt -> IO ()+foreign import capi safe "CTS_SHA3.h CTS_FIPS202_SHAKE128"+  c_safe_FIPS202_SHAKE128 :: Ptr Word8 -> CUInt -> Ptr Word8 -> CUInt -> IO ()+++foreign import capi unsafe "CTS_SHA3.h CTS_FIPS202_SHAKE256"+  c_unsafe_FIPS202_SHAKE256 :: Ptr Word8 -> CUInt -> Ptr Word8 -> CUInt -> IO ()+foreign import capi safe "CTS_SHA3.h CTS_FIPS202_SHAKE256"+  c_safe_FIPS202_SHAKE256 :: Ptr Word8 -> CUInt -> Ptr Word8 -> CUInt -> IO ()+++{-+ /Users/carter/WorkSpace/active/SecureHash-SHA3/cbits/CTS_SHA3.h: line 80, column 1:+    error:+     warning: unused function 'CTS_FIPS202_SHAKE128' [-Wunused-function]+   |+80 | static void CTS_FIPS202_SHAKE128(const unsigned char *input, unsigned int inputByteLen, unsigned char *output, int outputByteLen)+   |             ^++  /Users/carter/WorkSpace/active/SecureHash-SHA3/cbits/CTS_SHA3.h: line 88, column 1:+    error:+     warning: unused function 'CTS_FIPS202_SHAKE256' [-Wunused-function]+   |+88 | static void CTS_FIPS202_SHAKE256(const unsigned char *input, unsigned int inputByteLen, unsigned char *output, int outputByteLen)+   |             ^++  /Users/carter/WorkSpace/active/SecureHash-SHA3/cbits/CTS_SHA3.h: line 96, column 1:+    error:+     warning: unused function 'CTS_FIPS202_SHA3_224' [-Wunused-function]+   |+96 | static void CTS_FIPS202_SHA3_224(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)+   |             ^++  /Users/carter/WorkSpace/active/SecureHash-SHA3/cbits/CTS_SHA3.h: line 112, column 1:+    error:+     warning: unused function 'CTS_FIPS202_SHA3_384' [-Wunused-function]+    |+112 | static void CTS_FIPS202_SHA3_384(const unsigned char *input, unsigned int inputByteLen, unsigned char *output)+    |             ^++-}