diff options
| author | Mattias Andrée <maandree@operamail.com> | 2014-11-13 04:31:43 +0100 | 
|---|---|---|
| committer | Mattias Andrée <maandree@operamail.com> | 2014-11-13 04:31:43 +0100 | 
| commit | 25d561ca9aa5054896bd7c556a3efc6f4663beed (patch) | |
| tree | a4e906d08feb44c13eea7421cfb63cbe575a2b8e /python3 | |
| parent | fix bug (diff) | |
| download | sha3sum-25d561ca9aa5054896bd7c556a3efc6f4663beed.tar.gz sha3sum-25d561ca9aa5054896bd7c556a3efc6f4663beed.tar.bz2 sha3sum-25d561ca9aa5054896bd7c556a3efc6f4663beed.tar.xz  | |
nuke...
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to 'python3')
| -rw-r--r-- | python3/sha3.py | 661 | ||||
| -rwxr-xr-x | python3/sha3sum.py | 386 | 
2 files changed, 0 insertions, 1047 deletions
diff --git a/python3/sha3.py b/python3/sha3.py deleted file mode 100644 index 639be46..0000000 --- a/python3/sha3.py +++ /dev/null @@ -1,661 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -''' -sha3sum – SHA-3 (Keccak) checksum calculator - -Copyright © 2013, 2014  Mattias Andrée (maandree@member.fsf.org) - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program.  If not, see <http://www.gnu.org/licenses/>. -''' - -class SHA3: -    ''' -    SHA-3/Keccak hash algorithm implementation -     -    @author  Mattias Andrée  (maandree@member.fsf.org) -    ''' -     -     -    KECCAK_SUFFIX = '' -    ''' -    :str  Suffix the message when calculating the Keccak hash sum -    ''' -     -    SHA3_SUFFIX = '01' -    ''' -    :str  Suffix the message when calculating the SHA-3 hash sum -    ''' -     -    RawSHAKE_SUFFIX = '11' -    ''' -    :str  Suffix the message when calculating the RawSHAKE hash sum -    ''' -     -    SHAKE_SUFFIX = '1111' -    ''' -    :str  Suffix the message when calculating the SHAKE hash sum -    ''' -     -     -    def __init__(self): -        ''' -        Constructor -        ''' -         -        self.RC = [0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, -                   0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, -                   0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, -                   0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003, -                   0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A, -                   0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008] -        ''' -        :list<int>  Round contants -        ''' -         -        self.B = [0] * 25 -        ''' -        :list<int>  Keccak-f round temporary -        ''' -         -        self.C = [0] * 5 -        ''' -        :list<int>  Keccak-f round temporary -        ''' -         -         -        (self.r, self.c, self.n, self.b, self.w, self.wmod, self.l, self.nr) = (0, 0, 0, 0, 0, 0, 0, 0) -        ''' -           r:int  The bitrate -           c:int  The capacity -           n:int  The output size -           b:int  The state size -           w:int  The word size -        wmod:int  The word mask -           l:int  ℓ, the binary logarithm of the word size -          nr:int  12 + 2ℓ, the number of rounds -        ''' -         -        self.S = None -        ''' -        :list<int>  The current state -        ''' -         -        self.M = None -        ''' -        :bytes  Left over water to fill the sponge with at next update -        ''' -     -     -     -    def rotate(self, x, n): -        ''' -        Rotate a word -         -        @param   x:int  The value to rotate -        @param   n:int  Rotation steps -        @return   :int  The value rotated -        ''' -        m = n % self.w -        return ((x >> (self.w - m)) + (x << m)) & self.wmod -     -     -    def rotate64(self, x, n): -        ''' -        Rotate a 64-bit word -         -        @param   x:int  The value to rotate -        @param   n:int  Rotation steps -        @return   :int  The value rotated -        ''' -        return ((x >> (64 - n)) + (x << n)) & 0xFFFFFFFFFFFFFFFF -     -     -    def lb(self, x): -        ''' -        Binary logarithm -         -        @param   x:int  The value of which to calculate the binary logarithm -        @return   :int  The binary logarithm -        ''' -        rc = 0 -        if (x & 0xFF00) != 0:  rc +=  8 ;  x >>=  8 -        if (x & 0x00F0) != 0:  rc +=  4 ;  x >>=  4 -        if (x & 0x000C) != 0:  rc +=  2 ;  x >>=  2 -        if (x & 0x0002) != 0:  rc +=  1 -        return rc -     -     -    def keccakFRound(self, A, rc): -        ''' -        Perform one round of computation -         -        @param   A:list<int>  The current state -        @param  rc:int        Round constant -        ''' -        if self.w == 64: -            # θ step (step 1 and 2 of 3) -            self.C[0] = (A[0]  ^ A[1])  ^ (A[2]  ^ A[3])  ^ A[4] -            self.C[2] = (A[10] ^ A[11]) ^ (A[12] ^ A[13]) ^ A[14] -            db = self.C[0] ^ self.rotate64(self.C[2], 1) -            self.C[4] = (A[20] ^ A[21]) ^ (A[22] ^ A[23]) ^ A[24] -            dd = self.C[2] ^ self.rotate64(self.C[4], 1) -            self.C[1] = (A[5]  ^ A[6])  ^ (A[7]  ^ A[8])  ^ A[9] -            da = self.C[4] ^ self.rotate64(self.C[1], 1) -            self.C[3] = (A[15] ^ A[16]) ^ (A[17] ^ A[18]) ^ A[19] -            dc = self.C[1] ^ self.rotate64(self.C[3], 1) -            de = self.C[3] ^ self.rotate64(self.C[0], 1) -             -            # ρ and π steps, with last part of θ -            self.B[0] = self.rotate64(A[0] ^ da, 0) -            self.B[1] = self.rotate64(A[15] ^ dd, 28) -            self.B[2] = self.rotate64(A[5] ^ db, 1) -            self.B[3] = self.rotate64(A[20] ^ de, 27) -            self.B[4] = self.rotate64(A[10] ^ dc, 62) -             -            self.B[5] = self.rotate64(A[6] ^ db, 44) -            self.B[6] = self.rotate64(A[21] ^ de, 20) -            self.B[7] = self.rotate64(A[11] ^ dc, 6) -            self.B[8] = self.rotate64(A[1] ^ da, 36) -            self.B[9] = self.rotate64(A[16] ^ dd, 55) -             -            self.B[10] = self.rotate64(A[12] ^ dc, 43) -            self.B[11] = self.rotate64(A[2] ^ da, 3) -            self.B[12] = self.rotate64(A[17] ^ dd, 25) -            self.B[13] = self.rotate64(A[7] ^ db, 10) -            self.B[14] = self.rotate64(A[22] ^ de, 39) -             -            self.B[15] = self.rotate64(A[18] ^ dd, 21) -            self.B[16] = self.rotate64(A[8] ^ db, 45) -            self.B[17] = self.rotate64(A[23] ^ de, 8) -            self.B[18] = self.rotate64(A[13] ^ dc, 15) -            self.B[19] = self.rotate64(A[3] ^ da, 41) -             -            self.B[20] = self.rotate64(A[24] ^ de, 14) -            self.B[21] = self.rotate64(A[14] ^ dc, 61) -            self.B[22] = self.rotate64(A[4] ^ da, 18) -            self.B[23] = self.rotate64(A[19] ^ dd, 56) -            self.B[24] = self.rotate64(A[9] ^ db, 2) -        else: -            # θ step (step 1 and 2 of 3) -            self.C[0] = (A[0]  ^ A[1])  ^ (A[2]  ^ A[3])  ^ A[4] -            self.C[2] = (A[10] ^ A[11]) ^ (A[12] ^ A[13]) ^ A[14] -            db = self.C[0] ^ self.rotate(self.C[2], 1) -            self.C[4] = (A[20] ^ A[21]) ^ (A[22] ^ A[23]) ^ A[24] -            dd = self.C[2] ^ self.rotate(self.C[4], 1) -            self.C[1] = (A[5]  ^ A[6])  ^ (A[7]  ^ A[8])  ^ A[9] -            da = self.C[4] ^ self.rotate(self.C[1], 1) -            self.C[3] = (A[15] ^ A[16]) ^ (A[17] ^ A[18]) ^ A[19] -            dc = self.C[1] ^ self.rotate(self.C[3], 1) -            de = self.C[3] ^ self.rotate(self.C[0], 1) -             -            # ρ and π steps, with last part of θ -            self.B[0] = self.rotate(A[0] ^ da, 0) -            self.B[1] = self.rotate(A[15] ^ dd, 28) -            self.B[2] = self.rotate(A[5] ^ db, 1) -            self.B[3] = self.rotate(A[20] ^ de, 27) -            self.B[4] = self.rotate(A[10] ^ dc, 62) -             -            self.B[5] = self.rotate(A[6] ^ db, 44) -            self.B[6] = self.rotate(A[21] ^ de, 20) -            self.B[7] = self.rotate(A[11] ^ dc, 6) -            self.B[8] = self.rotate(A[1] ^ da, 36) -            self.B[9] = self.rotate(A[16] ^ dd, 55) -             -            self.B[10] = self.rotate(A[12] ^ dc, 43) -            self.B[11] = self.rotate(A[2] ^ da, 3) -            self.B[12] = self.rotate(A[17] ^ dd, 25) -            self.B[13] = self.rotate(A[7] ^ db, 10) -            self.B[14] = self.rotate(A[22] ^ de, 39) -             -            self.B[15] = self.rotate(A[18] ^ dd, 21) -            self.B[16] = self.rotate(A[8] ^ db, 45) -            self.B[17] = self.rotate(A[23] ^ de, 8) -            self.B[18] = self.rotate(A[13] ^ dc, 15) -            self.B[19] = self.rotate(A[3] ^ da, 41) -             -            self.B[20] = self.rotate(A[24] ^ de, 14) -            self.B[21] = self.rotate(A[14] ^ dc, 61) -            self.B[22] = self.rotate(A[4] ^ da, 18) -            self.B[23] = self.rotate(A[19] ^ dd, 56) -            self.B[24] = self.rotate(A[9] ^ db, 2) -         -        # ξ step -        A[0] = self.B[0] ^ ((~(self.B[5])) & self.B[10]) -        A[1] = self.B[1] ^ ((~(self.B[6])) & self.B[11]) -        A[2] = self.B[2] ^ ((~(self.B[7])) & self.B[12]) -        A[3] = self.B[3] ^ ((~(self.B[8])) & self.B[13]) -        A[4] = self.B[4] ^ ((~(self.B[9])) & self.B[14]) -         -        A[5] = self.B[5] ^ ((~(self.B[10])) & self.B[15]) -        A[6] = self.B[6] ^ ((~(self.B[11])) & self.B[16]) -        A[7] = self.B[7] ^ ((~(self.B[12])) & self.B[17]) -        A[8] = self.B[8] ^ ((~(self.B[13])) & self.B[18]) -        A[9] = self.B[9] ^ ((~(self.B[14])) & self.B[19]) -         -        A[10] = self.B[10] ^ ((~(self.B[15])) & self.B[20]) -        A[11] = self.B[11] ^ ((~(self.B[16])) & self.B[21]) -        A[12] = self.B[12] ^ ((~(self.B[17])) & self.B[22]) -        A[13] = self.B[13] ^ ((~(self.B[18])) & self.B[23]) -        A[14] = self.B[14] ^ ((~(self.B[19])) & self.B[24]) -         -        A[15] = self.B[15] ^ ((~(self.B[20])) & self.B[0]) -        A[16] = self.B[16] ^ ((~(self.B[21])) & self.B[1]) -        A[17] = self.B[17] ^ ((~(self.B[22])) & self.B[2]) -        A[18] = self.B[18] ^ ((~(self.B[23])) & self.B[3]) -        A[19] = self.B[19] ^ ((~(self.B[24])) & self.B[4]) -         -        A[20] = self.B[20] ^ ((~(self.B[0])) & self.B[5]) -        A[21] = self.B[21] ^ ((~(self.B[1])) & self.B[6]) -        A[22] = self.B[22] ^ ((~(self.B[2])) & self.B[7]) -        A[23] = self.B[23] ^ ((~(self.B[3])) & self.B[8]) -        A[24] = self.B[24] ^ ((~(self.B[4])) & self.B[9]) -         -        # ι step -        A[0] ^= rc -     -     -    def keccakF(self, A): -        ''' -        Perform Keccak-f function -         -        @param  A:list<int>  The current state -        ''' -        if (self.nr == 24): -            self.keccakFRound(A, 0x0000000000000001) -            self.keccakFRound(A, 0x0000000000008082) -            self.keccakFRound(A, 0x800000000000808A) -            self.keccakFRound(A, 0x8000000080008000) -            self.keccakFRound(A, 0x000000000000808B) -            self.keccakFRound(A, 0x0000000080000001) -            self.keccakFRound(A, 0x8000000080008081) -            self.keccakFRound(A, 0x8000000000008009) -            self.keccakFRound(A, 0x000000000000008A) -            self.keccakFRound(A, 0x0000000000000088) -            self.keccakFRound(A, 0x0000000080008009) -            self.keccakFRound(A, 0x000000008000000A) -            self.keccakFRound(A, 0x000000008000808B) -            self.keccakFRound(A, 0x800000000000008B) -            self.keccakFRound(A, 0x8000000000008089) -            self.keccakFRound(A, 0x8000000000008003) -            self.keccakFRound(A, 0x8000000000008002) -            self.keccakFRound(A, 0x8000000000000080) -            self.keccakFRound(A, 0x000000000000800A) -            self.keccakFRound(A, 0x800000008000000A) -            self.keccakFRound(A, 0x8000000080008081) -            self.keccakFRound(A, 0x8000000000008080) -            self.keccakFRound(A, 0x0000000080000001) -            self.keccakFRound(A, 0x8000000080008008) -        else: -            for i in range(self.nr): -                self.keccakFRound(A, self.RC[i] & self.wmod) -     -     -    def toLane(self, message, n, ww, off): -        ''' -        Convert a chunk of byte:s to a word -         -        @param   message:bytes  The message -        @param         n:int    `min(len(message), rr)` -                      rr:int    Bitrate in bytes -        @param        ww:int    Word size in bytes -        @param       off:int    The offset in the message -        @return         :int    Lane -        ''' -        rc = 0 -        i = off + ww - 1 -        while i >= off: -            rc = (rc << 8) | (message[i] if (i < n) else 0) -            i -= 1 -        return rc -     -     -    def toLane64(self, message, n, off): -        ''' -        Convert a chunk of byte:s to a 64-bit word -         -        @param   message:bytes  The message -        @param         n:int    `min(len(message), rr)` -                      rr:int    Bitrate in bytes -        @param       off:int    The offset in the message -        @return         :int    Lane -        ''' -        return ((message[off + 7] << 56) if (off + 7 < n) else 0) | ((message[off + 6] << 48) if (off + 6 < n) else 0) | ((message[off + 5] << 40) if (off + 5 < n) else 0) | ((message[off + 4] << 32) if (off + 4 < n) else 0) | ((message[off + 3] << 24) if (off + 3 < n) else 0) | ((message[off + 2] << 16) if (off + 2 < n) else 0) | ((message[off + 1] <<  8) if (off + 1 < n) else 0) | ((message[off]) if (off < n) else 0) -     -     -    def pad10star1(self, msg, r, bits): -        ''' -        pad 10*1 -         -        @param    msg:bytes  The message to pad -        @param      r:int    The bitrate -        @param   bits:int    The number of bits in the end of the message that does not make a whole byte -        @return      :bytes  The message padded -        ''' -        nnn = ((len(msg) - (bits + 7) // 8) << 3) + bits -         -        nrf = nnn >> 3 -        nbrf = nnn & 7 -        ll = nnn % r -         -        bbbb = 1 if nbrf == 0 else (msg[nrf] | (1 << nbrf)) -         -        message = None -        if ((r - 8 <= ll) and (ll <= r - 2)): -            message = [bbbb ^ 128] -        else: -            nnn = (nrf + 1) << 3 -            nnn = ((nnn - (nnn % r) + (r - 8)) >> 3) + 1 -            message = [0] * (nnn - nrf) -            message[0] = bbbb -            nnn -= nrf -            message[nnn - 1] = 0x80 -         -        return msg[:nrf] + bytes(message) -     -     -    def initialise(self, r, c, n): -        ''' -        Initialise Keccak sponge -         -        @param  r:int  The bitrate -        @param  c:int  The capacity -        @param  n:int  The output size -        ''' -        self.r = r -        self.c = c -        self.n = n -        self.b = r + c -        self.w = self.b // 25 -        self.l = self.lb(self.w) -        self.nr = 12 + (self.l << 1) -        self.wmod = (1 << self.w) - 1 -        self.S = [0] * 25 -        self.M = bytes([]) -     -     -    def update(self, msg, msglen = None): -        ''' -        Absorb the more of the message message to the Keccak sponge -         -        @param  msg:bytes   The partial message -        @param  msglen:int  The length of the partial message in whole bytes -        ''' -        if msglen is not None: -            msg = msg[:msglen] -         -        rr = self.r >> 3 -        ww = self.w >> 3 -         -        self.M += msg -        nnn = len(self.M) -        nnn -= nnn % ((self.r * self.b) >> 3) -        message = self.M[:nnn] -        self.M = self.M[nnn:] -         -        # Absorbing phase -        if ww == 8: -            for i in range(0, nnn, rr): -                n = min(len(message), rr) -                self.S[ 0] ^= self.toLane64(message, n, 0) -                self.S[ 5] ^= self.toLane64(message, n, 8) -                self.S[10] ^= self.toLane64(message, n, 16) -                self.S[15] ^= self.toLane64(message, n, 24) -                self.S[20] ^= self.toLane64(message, n, 32) -                self.S[ 1] ^= self.toLane64(message, n, 40) -                self.S[ 6] ^= self.toLane64(message, n, 48) -                self.S[11] ^= self.toLane64(message, n, 56) -                self.S[16] ^= self.toLane64(message, n, 64) -                self.S[21] ^= self.toLane64(message, n, 72) -                self.S[ 2] ^= self.toLane64(message, n, 80) -                self.S[ 7] ^= self.toLane64(message, n, 88) -                self.S[12] ^= self.toLane64(message, n, 96) -                self.S[17] ^= self.toLane64(message, n, 104) -                self.S[22] ^= self.toLane64(message, n, 112) -                self.S[ 3] ^= self.toLane64(message, n, 120) -                self.S[ 8] ^= self.toLane64(message, n, 128) -                self.S[13] ^= self.toLane64(message, n, 136) -                self.S[18] ^= self.toLane64(message, n, 144) -                self.S[23] ^= self.toLane64(message, n, 152) -                self.S[ 4] ^= self.toLane64(message, n, 160) -                self.S[ 9] ^= self.toLane64(message, n, 168) -                self.S[14] ^= self.toLane64(message, n, 176) -                self.S[19] ^= self.toLane64(message, n, 184) -                self.S[24] ^= self.toLane64(message, n, 192) -                self.keccakF(self.S) -                message = message[rr:] -        else: -            for i in range(0, nnn, rr): -                n = min(len(message), rr) -                self.S[ 0] ^= self.toLane(message, n, ww,  0) -                self.S[ 5] ^= self.toLane(message, n, ww,      ww) -                self.S[10] ^= self.toLane(message, n, ww,  2 * ww) -                self.S[15] ^= self.toLane(message, n, ww,  3 * ww) -                self.S[20] ^= self.toLane(message, n, ww,  4 * ww) -                self.S[ 1] ^= self.toLane(message, n, ww,  5 * ww) -                self.S[ 6] ^= self.toLane(message, n, ww,  6 * ww) -                self.S[11] ^= self.toLane(message, n, ww,  7 * ww) -                self.S[16] ^= self.toLane(message, n, ww,  8 * ww) -                self.S[21] ^= self.toLane(message, n, ww,  9 * ww) -                self.S[ 2] ^= self.toLane(message, n, ww, 10 * ww) -                self.S[ 7] ^= self.toLane(message, n, ww, 11 * ww) -                self.S[12] ^= self.toLane(message, n, ww, 12 * ww) -                self.S[17] ^= self.toLane(message, n, ww, 13 * ww) -                self.S[22] ^= self.toLane(message, n, ww, 14 * ww) -                self.S[ 3] ^= self.toLane(message, n, ww, 15 * ww) -                self.S[ 8] ^= self.toLane(message, n, ww, 16 * ww) -                self.S[13] ^= self.toLane(message, n, ww, 17 * ww) -                self.S[18] ^= self.toLane(message, n, ww, 18 * ww) -                self.S[23] ^= self.toLane(message, n, ww, 19 * ww) -                self.S[ 4] ^= self.toLane(message, n, ww, 20 * ww) -                self.S[ 9] ^= self.toLane(message, n, ww, 21 * ww) -                self.S[14] ^= self.toLane(message, n, ww, 22 * ww) -                self.S[19] ^= self.toLane(message, n, ww, 23 * ww) -                self.S[24] ^= self.toLane(message, n, ww, 24 * ww) -                self.keccakF(self.S) -                message = message[rr:] -     -     -    def digest(self, msg = None, msglen = None, bits = 0, suffix = SHA3_SUFFIX, withReturn = False): -        ''' -        Absorb the last part of the message and squeeze the Keccak sponge -         -        @param   msg:bytes?       The rest of the message -        @param   msglen:int       The length of the partial message in whole bytes -        @param   bits:int         The number of bits at the end of the message not covered by `msglen` -        @param   suffix:str       The suffix concatenate to the message -        @param   withReturn:bool  Whether to return the hash instead of just do a quick squeeze phrase and return `None` -        @return  :bytes?          The hash sum, or `None` if `withReturn` is `False` -        ''' -        if msg is None: -            msg, last_byte = bytes([]), 0 -            bits = 0 -        else: -            msg, last_byte = msg[:msglen + bits // 8], (0 if bits % 8 == 0 else msg[msglen]) -            bits %= 8 -            last_byte &= (1 << bits) - 1 -        msg_end = [] -        for bit in suffix: -            last_byte |= int(bit) << bits -            bits += 1 -            if bits == 8: -                msg_end.append(last_byte) -                last_byte = 0 -                bits = 0 -        if not bits == 0: -            msg_end.append(last_byte) -        msg += bytes(msg_end) -        message = self.pad10star1(self.M + msg, self.r, bits) -        self.M = None -        nnn = len(message) -         -        rr = self.r >> 3 -        nn = (self.n + 7) >> 3 -        ww = self.w >> 3 -         -        # Absorbing phase -        if ww == 8: -            for i in range(0, nnn, rr): -                n = min(len(message), rr) -                self.S[ 0] ^= self.toLane64(message, n, 0) -                self.S[ 5] ^= self.toLane64(message, n, 8) -                self.S[10] ^= self.toLane64(message, n, 16) -                self.S[15] ^= self.toLane64(message, n, 24) -                self.S[20] ^= self.toLane64(message, n, 32) -                self.S[ 1] ^= self.toLane64(message, n, 40) -                self.S[ 6] ^= self.toLane64(message, n, 48) -                self.S[11] ^= self.toLane64(message, n, 56) -                self.S[16] ^= self.toLane64(message, n, 64) -                self.S[21] ^= self.toLane64(message, n, 72) -                self.S[ 2] ^= self.toLane64(message, n, 80) -                self.S[ 7] ^= self.toLane64(message, n, 88) -                self.S[12] ^= self.toLane64(message, n, 96) -                self.S[17] ^= self.toLane64(message, n, 104) -                self.S[22] ^= self.toLane64(message, n, 112) -                self.S[ 3] ^= self.toLane64(message, n, 120) -                self.S[ 8] ^= self.toLane64(message, n, 128) -                self.S[13] ^= self.toLane64(message, n, 136) -                self.S[18] ^= self.toLane64(message, n, 144) -                self.S[23] ^= self.toLane64(message, n, 152) -                self.S[ 4] ^= self.toLane64(message, n, 160) -                self.S[ 9] ^= self.toLane64(message, n, 168) -                self.S[14] ^= self.toLane64(message, n, 176) -                self.S[19] ^= self.toLane64(message, n, 184) -                self.S[24] ^= self.toLane64(message, n, 192) -                self.keccakF(self.S) -                message = message[rr:] -        else: -            for i in range(0, nnn, rr): -                n = min(len(message), rr) -                self.S[ 0] ^= self.toLane(message, n, ww,  0) -                self.S[ 5] ^= self.toLane(message, n, ww,      ww) -                self.S[10] ^= self.toLane(message, n, ww,  2 * ww) -                self.S[15] ^= self.toLane(message, n, ww,  3 * ww) -                self.S[20] ^= self.toLane(message, n, ww,  4 * ww) -                self.S[ 1] ^= self.toLane(message, n, ww,  5 * ww) -                self.S[ 6] ^= self.toLane(message, n, ww,  6 * ww) -                self.S[11] ^= self.toLane(message, n, ww,  7 * ww) -                self.S[16] ^= self.toLane(message, n, ww,  8 * ww) -                self.S[21] ^= self.toLane(message, n, ww,  9 * ww) -                self.S[ 2] ^= self.toLane(message, n, ww, 10 * ww) -                self.S[ 7] ^= self.toLane(message, n, ww, 11 * ww) -                self.S[12] ^= self.toLane(message, n, ww, 12 * ww) -                self.S[17] ^= self.toLane(message, n, ww, 13 * ww) -                self.S[22] ^= self.toLane(message, n, ww, 14 * ww) -                self.S[ 3] ^= self.toLane(message, n, ww, 15 * ww) -                self.S[ 8] ^= self.toLane(message, n, ww, 16 * ww) -                self.S[13] ^= self.toLane(message, n, ww, 17 * ww) -                self.S[18] ^= self.toLane(message, n, ww, 18 * ww) -                self.S[23] ^= self.toLane(message, n, ww, 19 * ww) -                self.S[ 4] ^= self.toLane(message, n, ww, 20 * ww) -                self.S[ 9] ^= self.toLane(message, n, ww, 21 * ww) -                self.S[14] ^= self.toLane(message, n, ww, 22 * ww) -                self.S[19] ^= self.toLane(message, n, ww, 23 * ww) -                self.S[24] ^= self.toLane(message, n, ww, 24 * ww) -                self.keccakF(self.S) -                message = message[rr:] -         -        # Squeezing phase -        if withReturn: -            rc = [0] * ((self.n + 7) >> 3) -            ptr = 0 -             -            olen = self.n -            j = 0 -            ni = rr // ww -            while olen > 0: -                i = 0 -                while (i < ni) and (j < nn): -                    v = self.S[(i % 5) * 5 + i // 5] -                    for _ in range(ww): -                        if j < nn: -                            rc[ptr] = v & 255 -                            ptr += 1 -                        v >>= 8 -                        j += 1 -                    i += 1 -                olen -= self.r -                if olen > 0: -                    self.keccakF(self.S) -            if (self.n & 7) != 0: -                rc[len(rc) - 1] &= (1 << (self.n & 7)) - 1 -             -            return bytes(rc) -         -        olen = self.n -        while olen > self.r: -            olen -= self.r -            self.keccakF(self.S) -        return None -     -     -    def simpleSqueeze(self, times = 1): -        ''' -        Force some rounds of Keccak-f -         -        @param  times:int  The number of rounds -        ''' -        for i in range(times): -            self.keccakF(self.S) -     -     -    def fastSqueeze(self, times = 1): -        ''' -        Squeeze as much as is needed to get a digest a number of times -         -        @param  times:int  The number of digests -        ''' -        for i in range(times): -            self.keccakF(self.S) # Last squeeze did not do a ending squeeze -            olen = self.n -            while olen > self.r: -                olen -= self.r -                self.keccakF(self.S) -     -     -    def squeeze(self): -        ''' -        Squeeze out another digest -         -        @return  :bytes  The hash sum -        ''' -        self.keccakF(self.S) # Last squeeze did not do a ending squeeze -         -        nn = (self.n + 7) >> 3 -        ww = self.w >> 3 -        rc = [0] * nn -        olen = self.n -        j = 0 -        ptr = 0 -        ni = (self.r >> 3) // ww -         -        while olen > 0: -            i = 0 -            while (i < ni) and (j < nn): -                v = self.S[(i % 5) * 5 + i // 5] -                for _ in range(ww): -                    if j < nn: -                        rc[ptr] = v -                        ptr += 1 -                    v >>= 8 -                    j += 1 -                i += 1 -            olen -= self.r -            if olen > 0: -                self.keccakF(self.S) -         -        if (self.n & 7) != 0: -            rc[len(rc) - 1] &= (1 << (self.n & 7)) - 1 -         -        return bytes(rc) - diff --git a/python3/sha3sum.py b/python3/sha3sum.py deleted file mode 100755 index 93d3e72..0000000 --- a/python3/sha3sum.py +++ /dev/null @@ -1,386 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -''' -sha3sum – SHA-3 (Keccak) checksum calculator - -Copyright © 2013, 2014  Mattias Andrée (maandree@member.fsf.org) - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program.  If not, see <http://www.gnu.org/licenses/>. -''' - -import sys -import os - -from sha3 import SHA3 - - -def printerr(text, end = '\n'): -    sys.stderr.buffer.write((text + end).encode('utf-8')) -    sys.stderr.buffer.flush() - - -if __name__ == '__main__': -    cmd = sys.argv[0] -    args = sys.argv[1:] -    if '/' in cmd: -        cmd = cmd[cmd.rfind('/') + 1:] -    if cmd.endswith('.py'): -        cmd = cmd[:-3] -     -    (O, S, R, C, W, I, J) = (None, None, None, None, None, None, None) -    (o, s, r, c, w, i, j) = (0, 0, 0, 0, 0, 0, 0) -    _o = 512             # --outputsize -    if   cmd == 'sha3-224sum':  _o = 224 -    elif cmd == 'sha3-256sum':  _o = 256 -    elif cmd == 'sha3-384sum':  _o = 384 -    elif cmd == 'sha3-512sum':  _o = 512 -    _s = 1600            # --statesize -    _c = _s - (_o << 1)  # --capacity -    _r = _s - _c         # --bitrate -    _w = _s / 25         # --wordsize -    _i = 1               # --iterations -    _j = 1               # --squeezes -    (binary, hex, multi) = (False, False, 0) -     -    files = [] -    dashed = False -    linger = None -     -    for arg in args + [None]: -        if linger is not None: -            if linger[0] in ('-h', '--help'): -                sys.stderr.buffer.write((''' -SHA-3/Keccak checksum calculator - -USAGE:  sha3sum [option...] < file -        sha3sum [option...] file... - - -OPTIONS: -        -r BITRATE -        --bitrate       The bitrate to use for checksum.        (default: %d) -         -        -c CAPACITY -        --capacity      The capacity to use for checksum.       (default: %d) -         -        -w WORDSIZE -        --wordsize      The word size to use for checksum.      (default: %d) -         -        -o OUTPUTSIZE -        --outputsize    The output size to use for checksum.    (default: %d) -         -        -s STATESIZE -        --statesize     The state size to use for checksum.     (default: %d) -         -        -i ITERATIONS -        --iterations    The number of hash iterations to run.   (default: %d) -         -        -j SQUEEZES -        --squeezes      The number of hash squeezes to run.     (default: %d) -         -        -x -        --hex           Read the input in hexadecimal, rather than binary. -         -        -b -        --binary        Print the checksum in binary, rather than hexadecimal. -         -        -m -        --multi         Print the checksum at all iterations. - - -COPYRIGHT: - -Copyright © 2013, 2014  Mattias Andrée (maandree@member.fsf.org) - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -GNU Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program.  If not, see <http://www.gnu.org/licenses/>. - -''' % (_r, _c, _w, _o, _s, _i, _j)).encode('utf-8')) -                sys.stderr.buffer.flush() -                exit(0) -            else: -                if linger[1] is None: -                    linger[1] = arg -                    arg = None -                if linger[0] in ('-r', '--bitrate'): -                    R = int(linger[1]) -                elif linger[0] in ('-c', '--capacity'): -                    C = int(linger[1]) -                elif linger[0] in ('-w', '--wordsize'): -                    W = int(linger[1]) -                elif linger[0] in ('-o', '--outputsize'): -                    O = int(linger[1]) -                elif linger[0] in ('-s', '--statesize'): -                    S = int(linger[1]) -                elif linger[0] in ('-i', '--iterations'): -                    I = int(linger[1]) -                elif linger[0] in ('-j', '--squeezes'): -                    J = int(linger[1]) -                else: -                    printerr(sys.argv[0] + ': unrecognised option: ' + linger[0]) -                    sys.exit(1) -            linger = None -            if arg is None: -                continue -        if arg is None: -            continue -        if dashed: -            files.append(None if arg == '-' else arg) -        elif arg == '--': -            dashed = True -        elif arg == '-': -            files.append(None) -        elif arg.startswith('--'): -            if '=' in arg: -                linger = (arg[:arg.find('=')], arg[arg.find('=') + 1:]) -            else: -                if arg == '--binary': -                    binary = True -                elif arg == '--multi': -                    multi += 1 -                elif arg == '--hex': -                    hex = True -                else: -                    linger = [arg, None] -        elif arg.startswith('-'): -            arg = arg[1:] -            if arg[0] == 'b': -                binary = True -                arg = arg[1:] -            elif arg[0] == 'b': -                multi += 1 -                arg = arg[1:] -            elif arg[0] == 'x': -                hex = True -                arg = arg[1:] -            elif len(arg) == 1: -                linger = ['-' + arg, None] -            else: -                linger = ['-' + arg[0], arg[1:]] -        else: -            files.append(arg) -     -     -    i = _i if I is None else I -    j = _j if J is None else J -     -     -    if S is not None: -        s = S -        if ((s <= 0) or (s > 1600) or (s % 25 != 0)): -            printerr(cmd + ': the state size must be a positive multiple of 25 and is limited to 1600.') -            sys.exit(6) -     -    if W is not None: -        w = W -        if (w <= 0) or (w > 64): -            printerr(cmd + ': the word size must be positive and is limited to 64.') -            sys.exit(6) -        if (S is not None) and (s != w * 25): -            printerr(cmd + ': the state size must be 25 times of the word size.') -            sys.exit(6) -        elif S is None: -            S = w * 25 -     -    if C is not None: -        c = C -        if (c <= 0) or ((c & 7) != 0): -            printerr(cmd + ': the capacity must be a positive multiple of 8.') -            sys.exit(6) -     -    if R is not None: -        r = R -        if (r <= 0) or ((r & 7) != 0): -            printerr(cmd + ': the bitrate must be a positive multiple of 8.') -            sys.exit(6) -     -    if O is not None: -        o = O -        if o <= 0: -            printerr(cmd + ': the output size must be positive.') -            sys.exit(6) -     -     -    if (R is None) and (C is None) and (O is None): ## s? -        s = _s if S is None else s -        o = (((s << 5) // 100 + 7) >> 3) << 3 -        r = o << 1 -        c = s - r -        o = 8 if o < 8 else o -    elif (R is None) and (C is None): ## !o s? -        r = _r -        c = _c -        s = (r + c) if S is None else s -    elif R is None: ## !c o? s? -        s = _s if S is None else s -        r = s - c -        o = (8 if c == 8 else (c << 1)) if O is None else o -    elif C is None: ## !r o? s? -        s = _s if S is None else s -        c = s - r -        o = (8 if c == 8 else (c << 1)) if O is None else o -    else: ## !r !c o? s? -        s = (r + c) if S is None else s -        o = (8 if c == 8 else (c << 1)) if O is None else o -     -     -    printerr('Bitrate: %d' % r) -    printerr('Capacity: %d' % c) -    printerr('Word size: %d' % w) -    printerr('State size: %d' % s) -    printerr('Output size: %d' % o) -    printerr('Iterations: %d' % i) -    printerr('Squeezes: %d' % j) -     -     -    if r > s: -        printerr(cmd + ': the bitrate must not be higher than the state size.') -        sys.exit(6) -    if c > s: -        printerr(cmd + ': the capacity must not be higher than the state size.') -        sys.exit(6) -    if r + c != s: -        printerr(cmd + ': the sum of the bitrate and the capacity must equal the state size.') -        sys.exit(6) -     -     -    if len(files) == 0: -        files.append(None) -    if i < 1: -        printerr(cmd + ': sorry, I will only do at least one hash iteration!\n') -        sys.exit(3) -    if j < 1: -        printerr(cmd + ': sorry, I will only do at least one squeeze iteration!\n') -        sys.exit(3) -    stdin = None -    fail = False -    sha = SHA3() -    for filename in files: -        rc = '' -        fn = '/dev/stdin' if filename is None else filename -        with open(fn, 'rb') as file: -            try: -                if (filename is not None) or (stdin is None): -                    sha.initialise(r, c, o) -                    blksize = 4096 -                    try: -                        blksize = os.stat(os.path.realpath(fn)).st_blksize -                        if blksize <= 0: -                            blksize = 4096 -                    except: -                        pass -                    while True: -                        chunk = file.read(blksize) -                        if len(chunk) == 0: -                            break -                        if not hex: -                            sha.update(chunk) -                        else: -                            chunk = list(chunk) -                            n = len(chunk) >> 1 -                            for _ in range(n): -                                (a, b) = (chunk[_ << 1], chunk[(_ << 1 | 1)]) -                                a = ((a & 15) + (0 if a <= '9' else 9)) << 4 -                                b =  (b & 15) + (0 if b <= '9' else 0) -                                chunk[_] = a | b -                            sha.update(bytes(chunk), n) -                    bs = sha.digest(withReturn = j == 1) -                    if j > 2: -                        sha.fastSqueeze(j - 2) -                    if j > 1: -                        bs = sha.squeeze(); -                    if filename is None: -                        stdin = bs -                else: -                    bs = stdin -                if multi == 0: -                    for _ in range(i - 1): -                        sha.initialise(r, c, o) -                        bs = sha.digest(bs, withReturn = j == 1) -                        if j > 2: -                            sha.fastSqueeze(j - 2) -                        if j > 1: -                            bs = sha.squeeze(); -                    if binary: -                        sys.stdout.buffer.write(bs) -                    else: -                        for b in bs: -                            rc += "0123456789ABCDEF"[b >> 4] -                            rc += "0123456789ABCDEF"[b & 15] -                        rc += ' ' + ('-' if filename is None else filename) + '\n' -                        sys.stdout.buffer.write(rc.encode('utf-8')) -                elif multi == 1: -                    if binary: -                        sys.stdout.buffer.write(bs) -                    else: -                        for b in bs: -                            rc += "0123456789ABCDEF"[b >> 4] -                            rc += "0123456789ABCDEF"[b & 15] -                        rc += '\n' -                        sys.stdout.buffer.write(rc.encode('UTF-8')) -                    for _ in range(i - 1): -                        sha.initialise(r, c, o) -                        bs = sha.digest(bs, j == 1) -                        if j > 2: -                            sha.fastSqueeze(j - 2) -                        if j > 1: -                            bs = sha.squeeze(); -                        if binary: -                            sys.stdout.buffer.write(bs); -                        else: -                            rc = '' -                            for b in bs: -                                rc += "0123456789ABCDEF"[b >> 4] -                                rc += "0123456789ABCDEF"[b & 15] -                            rc += '\n' -                            sys.stdout.buffer.write(rc.encode('UTF-8')) -                else: -                    got = set() -                    loop = None -                    for _ in range(i): -                        if _ > 0: -                            pass -                        rc = '' -                        for b in bs: -                            rc += "0123456789ABCDEF"[b >> 4] -                            rc += "0123456789ABCDEF"[b & 15] -                        if loop is None: -                            if rc in got: -                                loop = rc -                            else: -                                got.add(rc) -                        if loop == rc: -                            rc = '\033[31m%s\033[00m' % rc; -                        sys.stdout.buffer.write(rc.encode('utf-8')) -                        sys.stdout.buffer.flush() -                    if loop is not None: -                        printerr('\033[01;31mLoop found\033[00m') -                sys.stdout.buffer.flush() -            except Exception as err: -                printerr(cmd + ': cannot read file: ' + fn + ': ' + str(err)) -                fail = True -        sys.stdout.buffer.flush() -    if fail: -        sys.exit(5) -  | 
