Skip to content
This repository was archived by the owner on Jan 13, 2023. It is now read-only.

Commit 9e1154d

Browse files
committed
Quick and dirty PyKerl install.
1 parent 85bbc7d commit 9e1154d

File tree

10 files changed

+30668
-2
lines changed

10 files changed

+30668
-2
lines changed

iota/crypto/kerl/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# coding=utf-8
2+
from __future__ import absolute_import, division, print_function, \
3+
unicode_literals
4+
5+
from six import PY3
6+
7+
if PY3:
8+
# noinspection SpellCheckingInspection
9+
from . import pykerl_py3 as pykerl
10+
else:
11+
# noinspection SpellCheckingInspection
12+
from . import pykerl_py2 as pykerl

iota/crypto/kerl/conv.py

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# coding=utf-8
2+
from __future__ import absolute_import, division, print_function, \
3+
unicode_literals
4+
5+
6+
BYTE_HASH_LENGTH = 48
7+
TRIT_HASH_LENGTH = 243
8+
9+
tryte_table = {
10+
'9': [ 0, 0, 0], # 0
11+
'A': [ 1, 0, 0], # 1
12+
'B': [-1, 1, 0], # 2
13+
'C': [ 0, 1, 0], # 3
14+
'D': [ 1, 1, 0], # 4
15+
'E': [-1, -1, 1], # 5
16+
'F': [ 0, -1, 1], # 6
17+
'G': [ 1, -1, 1], # 7
18+
'H': [-1, 0, 1], # 8
19+
'I': [ 0, 0, 1], # 9
20+
'J': [ 1, 0, 1], # 10
21+
'K': [-1, 1, 1], # 11
22+
'L': [ 0, 1, 1], # 12
23+
'M': [ 1, 1, 1], # 13
24+
'N': [-1, -1, -1], # -13
25+
'O': [ 0, -1, -1], # -12
26+
'P': [ 1, -1, -1], # -11
27+
'Q': [-1, 0, -1], # -10
28+
'R': [ 0, 0, -1], # -9
29+
'S': [ 1, 0, -1], # -8
30+
'T': [-1, 1, -1], # -7
31+
'U': [ 0, 1, -1], # -6
32+
'V': [ 1, 1, -1], # -5
33+
'W': [-1, -1, 0], # -4
34+
'X': [ 0, -1, 0], # -3
35+
'Y': [ 1, -1, 0], # -2
36+
'Z': [-1, 0, 0], # -1
37+
}
38+
39+
# Invert for trit -> tryte lookup
40+
trit_table = {tuple(v): k for k, v in tryte_table.items()}
41+
42+
def trytes_to_trits(trytes):
43+
trits = []
44+
for tryte in trytes:
45+
trits.extend(tryte_table[tryte])
46+
47+
return trits
48+
49+
def trits_to_trytes(trits):
50+
trytes = []
51+
trits_chunks = [trits[i:i + 3] for i in range(0, len(trits), 3)]
52+
53+
for trit in trits_chunks:
54+
trytes.extend(trit_table[tuple(trit)])
55+
56+
return ''.join(trytes)
57+
58+
def convertToTrits(bytes_k):
59+
bigInt = convertBytesToBigInt(bytes_k)
60+
trits = convertBigintToBase(bigInt, 3, TRIT_HASH_LENGTH)
61+
return trits
62+
63+
def convertToBytes(trits):
64+
bigInt = convertBaseToBigint(trits, 3)
65+
bytes_k = convertBigintToBytes(bigInt)
66+
return bytes_k
67+
68+
def convertBytesToBigInt(ba):
69+
# copy of array
70+
bytesArray = list(map(lambda x: x, ba))
71+
72+
# number sign in MSB
73+
signum = (1 if bytesArray[0] >= 0 else -1)
74+
75+
if signum == -1:
76+
# sub1
77+
for pos in reversed(range(len(bytesArray))):
78+
sub = (bytesArray[pos] & 0xFF) - 1
79+
bytesArray[pos] = (sub if sub <= 0x7F else sub - 0x100)
80+
if bytesArray[pos] != -1:
81+
break
82+
83+
# 1-compliment
84+
bytesArray = list(map(lambda x: ~x, bytesArray))
85+
86+
# sum magnitudes and set sign
87+
return sum((x & 0xFF) << pos * 8 for (pos, x) in
88+
enumerate(reversed(bytesArray))) * signum
89+
90+
91+
def convertBigintToBytes(big):
92+
bytesArrayTemp = [(abs(big) >> pos * 8) % (1 << 8) for pos in
93+
range(48)]
94+
95+
# big endian and balanced
96+
bytesArray = list(map(lambda x: (x if x <= 0x7F else x - 0x100),
97+
reversed(bytesArrayTemp)))
98+
99+
if big < 0:
100+
# 1-compliment
101+
bytesArray = list(map(lambda x: ~x, bytesArray))
102+
103+
# add1
104+
for pos in reversed(range(len(bytesArray))):
105+
add = (bytesArray[pos] & 0xFF) + 1
106+
bytesArray[pos] = (add if add <= 0x7F else add - 0x100)
107+
if bytesArray[pos] != 0:
108+
break
109+
110+
return bytesArray
111+
112+
def convertBaseToBigint(array, base):
113+
bigint = 0
114+
115+
for i in range(len(array)):
116+
bigint += array[i] * (base ** i)
117+
118+
return bigint
119+
120+
def convertBigintToBase(bigInt, base, length):
121+
result = []
122+
123+
is_negative = bigInt < 0
124+
quotient = abs(bigInt)
125+
126+
MAX = (base-1) // 2
127+
if is_negative:
128+
MAX = base // 2
129+
130+
for i in range(length):
131+
quotient, remainder = divmod(quotient, base)
132+
133+
if remainder > MAX:
134+
# Lend 1 to the next place so we can make this digit negative.
135+
quotient += 1
136+
remainder -= base
137+
138+
if is_negative:
139+
remainder = remainder * -1
140+
141+
result.append(remainder)
142+
143+
return result
144+
145+
def convert_sign(byte):
146+
"""
147+
Convert between signed and unsigned bytes
148+
"""
149+
if byte < 0:
150+
return 256 + byte
151+
elif byte > 127:
152+
return -256 + byte
153+
return byte

iota/crypto/kerl/pykerl_py2.py

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# coding=utf-8
2+
from __future__ import absolute_import, division, print_function, \
3+
unicode_literals
4+
5+
from sha3 import keccak_384
6+
7+
from iota.exceptions import with_context
8+
9+
__all__ = [
10+
'Kerl',
11+
]
12+
13+
TRIT_HASH_LENGTH = 243
14+
BYTE_HASH_LENGTH = 48
15+
16+
class Kerl(object):
17+
def __init__(self):
18+
self._reset()
19+
20+
def absorb(self, trits, offset=0, length=None):
21+
if length is None:
22+
length = len(trits)
23+
24+
if length % 243:
25+
raise with_context(
26+
exc = ValueError('Illegal length (s/b divisible by 243).'),
27+
28+
context = {
29+
'length': length,
30+
},
31+
)
32+
33+
trits_state = []
34+
35+
while offset < length:
36+
stop = min(offset + TRIT_HASH_LENGTH, length)
37+
trits_state[0:stop - offset] = trits[offset:stop]
38+
39+
# Byte encoding
40+
trits_state[TRIT_HASH_LENGTH-1] = 0
41+
un_bytes =\
42+
self.convertBigintToBytes(self.convertTritsToBigint(trits_state))
43+
_bytes = map(lambda x: x % 256, un_bytes)
44+
45+
self.k.update(bytearray(_bytes))
46+
47+
# Move on to the next hash.
48+
offset += TRIT_HASH_LENGTH
49+
50+
51+
def squeeze(self, trits, offset=0, length=TRIT_HASH_LENGTH):
52+
if length % 243:
53+
raise with_context(
54+
exc = ValueError('Illegal length (s/b divisible by 243).'),
55+
56+
context = {
57+
'length': length,
58+
},
59+
)
60+
61+
while offset < length:
62+
bytes_state = bytearray.fromhex(self.k.hexdigest())
63+
_bytes = map(lambda x: x if x<=127 else x-256, bytes_state)
64+
65+
# Trits Encoding
66+
trits.extend([0] * max(0, TRIT_HASH_LENGTH - len(trits)))
67+
trits_state =\
68+
self.convertBigintToTrits(self.convertBytesToBigInt(_bytes))
69+
trits_state[TRIT_HASH_LENGTH - 1] = 0
70+
71+
# Copy exactly one hash.
72+
stop = min(TRIT_HASH_LENGTH, length)
73+
trits[offset:stop] = trits_state[0:stop]
74+
75+
# One hash worth of trits copied; now transform.
76+
bytes_state = map(lambda x: x ^ 0xFF, bytes_state)
77+
self._reset()
78+
self.k.update(bytearray(bytes_state))
79+
80+
offset += TRIT_HASH_LENGTH
81+
82+
def _reset(self):
83+
self.k = keccak_384()
84+
85+
@staticmethod
86+
def convertTritsToBigint(trits):
87+
return sum(base * (3 ** power) for power, base in enumerate(trits))
88+
89+
def convertBigintToTrits(self, n):
90+
return self.convertBigintToBase(n, 3, TRIT_HASH_LENGTH)
91+
92+
@staticmethod
93+
def convertBigintToBytes(big):
94+
bytesArrayTemp = [((abs(big) >> pos * 8) % (1 << 8)) for pos in range(48)]
95+
# Big endian and balanced
96+
bytesArray =\
97+
list(map(
98+
lambda x: x if x <= 0x7F else (x - 0x100),
99+
reversed(bytesArrayTemp)
100+
))
101+
102+
if big < 0:
103+
# 1-compliment
104+
bytesArray = list(map(lambda x: ~x, bytesArray))
105+
# Add 1
106+
for pos in reversed(range(len(bytesArray))):
107+
add = ((bytesArray[pos] & 0xFF) + 1)
108+
bytesArray[pos] = add if add <= 0x7F else (add - 0x100)
109+
if bytesArray[pos] != 0:
110+
break
111+
112+
return bytesArray
113+
114+
@staticmethod
115+
def convertBytesToBigInt(ba):
116+
# Copy of array
117+
bytesArray = list(map(lambda x: x, ba))
118+
# Number sign in MSB
119+
signum = 1 if bytesArray[0] >= 0 else -1
120+
121+
if signum == -1:
122+
# Subtract 1
123+
for pos in reversed(range(len(bytesArray))):
124+
sub = ((bytesArray[pos] & 0xFF) - 1)
125+
bytesArray[pos] = sub if sub <= 0x7F else (sub - 0x100)
126+
if bytesArray[pos] != -1:
127+
break
128+
# 1-compliment
129+
bytesArray = map(lambda x: ~x, bytesArray)
130+
131+
# Sum magnitudes and set sign.
132+
return (
133+
sum((x & 0xFF) << pos * 8
134+
for pos, x in enumerate(reversed(bytesArray))) * signum
135+
)
136+
137+
@staticmethod
138+
def convertBigintToBase(n, radix, pad):
139+
base = [0] * pad
140+
negative = n<0
141+
n = -n if negative else n
142+
max_ = int(radix / 2) if negative else int((radix - 1) / 2)
143+
144+
for i in range(pad):
145+
n, remainder = divmod(n, radix)
146+
147+
if remainder > max_:
148+
# Lend 1 to the next place so we can make this trit negative.
149+
n += 1
150+
remainder -= radix
151+
152+
base[i] = -remainder if negative else remainder
153+
154+
return base

0 commit comments

Comments
 (0)