Add files via upload
This commit is contained in:
parent
ab67e6099e
commit
c084e33544
|
@ -0,0 +1,11 @@
|
||||||
|
from prince64 import prince
|
||||||
|
|
||||||
|
plainfile = open("pt.dat", "rb")
|
||||||
|
cipherfile = open("ct.dat", "rb")
|
||||||
|
|
||||||
|
pbyte = plainfile.read(8)
|
||||||
|
cbyte = cipherfile.read(8)
|
||||||
|
pbytearay = [((a&0x0F)<<4)|((a&0xF0)>>4) for a in list(pbyte)][::-1]
|
||||||
|
cbytearay = [((a&0x0F)<<4)|((a&0xF0)>>4) for a in list(cbyte)][::-1]
|
||||||
|
a = prince(pbytearay,[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
|
||||||
|
a.start()
|
|
@ -0,0 +1,73 @@
|
||||||
|
from random import *
|
||||||
|
import math
|
||||||
|
A = 0
|
||||||
|
B = 7
|
||||||
|
P = 2**21 - 1# 2**256 - 2**224 + 2**192 + 2**96 - 1
|
||||||
|
|
||||||
|
def doubleing(point):
|
||||||
|
x1 = point[0]
|
||||||
|
y1 = point[1]
|
||||||
|
|
||||||
|
lamda = ((3*(x1**2)+A) % P) * ((2*y1)**(P-2) % P) % P
|
||||||
|
x2 = (lamda**2 - 2*x1) % P
|
||||||
|
y2 = ((x1 - x2)*lamda - y1) % P
|
||||||
|
|
||||||
|
return (x2, y2)
|
||||||
|
|
||||||
|
def adding(point1, point2):
|
||||||
|
x1 = point1[0]
|
||||||
|
y1 = point1[1]
|
||||||
|
x2 = point2[0]
|
||||||
|
y2 = point2[1]
|
||||||
|
|
||||||
|
lamda = (((y2 - y1) % P) * ((x2 - x1)**(P-2) % P)) % P
|
||||||
|
x3 = (lamda**2 - x1 - x2) % P
|
||||||
|
y3 = ((x1 - x3) * lamda - y1) % P
|
||||||
|
|
||||||
|
return (x3, y3)
|
||||||
|
|
||||||
|
def muling(point, n):
|
||||||
|
double = doubleing(point)
|
||||||
|
if(n==2):
|
||||||
|
return double
|
||||||
|
elif(n==1):
|
||||||
|
return point
|
||||||
|
else:
|
||||||
|
log2n = int(math.log(n, 2))
|
||||||
|
mul = {}
|
||||||
|
ddowl = double
|
||||||
|
num = 2
|
||||||
|
count = 1
|
||||||
|
mul[2] = double
|
||||||
|
mul[1] = point
|
||||||
|
|
||||||
|
while(log2n>count):
|
||||||
|
tmp = doubleing(ddowl)
|
||||||
|
num = num*2
|
||||||
|
mul[num] = tmp
|
||||||
|
ddowl = tmp
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
what = 1
|
||||||
|
whatadd = []
|
||||||
|
|
||||||
|
while(n):
|
||||||
|
if(n % 2 == 1):
|
||||||
|
whatadd.append(what)
|
||||||
|
what = what * 2
|
||||||
|
n = int(n / 2)
|
||||||
|
|
||||||
|
result = mul[whatadd[0]]
|
||||||
|
del(whatadd[0])
|
||||||
|
if len(whatadd) >= 1:
|
||||||
|
for i in whatadd:
|
||||||
|
result = adding(result,mul[i])
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
if __name__=="__main__":
|
||||||
|
count = randint(0,2**1000)
|
||||||
|
x1 = randint(0,2**1000)
|
||||||
|
y1 = randint(0,2**1000)
|
||||||
|
res = muling((x1,y1),count)
|
||||||
|
print(hex(count), res, sep='\n')
|
|
@ -0,0 +1,209 @@
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from random import randint
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PrimeGaloisField:
|
||||||
|
prime: int
|
||||||
|
|
||||||
|
def __contains__(self, field_value: "FieldElement") -> bool:
|
||||||
|
|
||||||
|
return 0 <= field_value.value < self.prime
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class FieldElement:
|
||||||
|
value: int
|
||||||
|
field: PrimeGaloisField
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "0x" + f"{self.value:x}".zfill(64)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def P(self) -> int:
|
||||||
|
return self.field.prime
|
||||||
|
|
||||||
|
def __add__(self, other: "FieldElement") -> "FieldElement":
|
||||||
|
return FieldElement(
|
||||||
|
value=(self.value + other.value) % self.P,
|
||||||
|
field=self.field
|
||||||
|
)
|
||||||
|
|
||||||
|
def __sub__(self, other: "FieldElement") -> "FieldElement":
|
||||||
|
return FieldElement(
|
||||||
|
value=(self.value - other.value) % self.P,
|
||||||
|
field=self.field
|
||||||
|
)
|
||||||
|
|
||||||
|
def __rmul__(self, scalar: int) -> "FieldValue":
|
||||||
|
return FieldElement(
|
||||||
|
value=(self.value * scalar) % self.P,
|
||||||
|
field=self.field
|
||||||
|
)
|
||||||
|
|
||||||
|
def __mul__(self, other: "FieldElement") -> "FieldElement":
|
||||||
|
return FieldElement(
|
||||||
|
value=(self.value * other.value) % self.P,
|
||||||
|
field=self.field
|
||||||
|
)
|
||||||
|
|
||||||
|
def __pow__(self, exponent: int) -> "FieldElement":
|
||||||
|
return FieldElement(
|
||||||
|
value=pow(self.value, exponent, self.P),
|
||||||
|
field=self.field
|
||||||
|
)
|
||||||
|
|
||||||
|
def __truediv__(self, other: "FieldElement") -> "FieldElement":
|
||||||
|
other_inv = other ** -1
|
||||||
|
return self * other_inv
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class EllipticCurve:
|
||||||
|
a: int
|
||||||
|
b: int
|
||||||
|
|
||||||
|
field: PrimeGaloisField
|
||||||
|
|
||||||
|
def __contains__(self, point: "Point") -> bool:
|
||||||
|
x, y = point.x, point.y
|
||||||
|
return y ** 2 == x ** 3 + self.a * x + self.b
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
|
||||||
|
self.a = FieldElement(self.a, self.field)
|
||||||
|
self.b = FieldElement(self.b, self.field)
|
||||||
|
|
||||||
|
if self.a not in self.field or self.b not in self.field:
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Point:
|
||||||
|
x: int
|
||||||
|
y: int
|
||||||
|
|
||||||
|
curve: EllipticCurve
|
||||||
|
|
||||||
|
def __post_init__(self):
|
||||||
|
|
||||||
|
if self.x is None and self.y is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.x = FieldElement(self.x, self.curve.field)
|
||||||
|
self.y = FieldElement(self.y, self.curve.field)
|
||||||
|
|
||||||
|
if self not in self.curve:
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
|
||||||
|
if self == I:
|
||||||
|
return other
|
||||||
|
|
||||||
|
if other == I:
|
||||||
|
return self
|
||||||
|
|
||||||
|
if self.x == other.x and self.y == (-1 * other.y):
|
||||||
|
return I
|
||||||
|
|
||||||
|
if self.x != other.x:
|
||||||
|
x1, x2 = self.x, other.x
|
||||||
|
y1, y2 = self.y, other.y
|
||||||
|
|
||||||
|
s = (y2 - y1) / (x2 - x1)
|
||||||
|
x3 = s ** 2 - x1 - x2
|
||||||
|
y3 = s * (x1 - x3) - y1
|
||||||
|
|
||||||
|
return self.__class__(
|
||||||
|
x=x3.value,
|
||||||
|
y=y3.value,
|
||||||
|
curve=secp256k1
|
||||||
|
)
|
||||||
|
|
||||||
|
if self == other and self.y == inf:
|
||||||
|
return I
|
||||||
|
|
||||||
|
if self == other:
|
||||||
|
x1, y1, a = self.x, self.y, self.curve.a
|
||||||
|
|
||||||
|
s = (3 * x1 ** 2 + a) / (2 * y1)
|
||||||
|
x3 = s ** 2 - 2 * x1
|
||||||
|
y3 = s * (x1 - x3) - y1
|
||||||
|
|
||||||
|
return self.__class__(
|
||||||
|
x=x3.value,
|
||||||
|
y=y3.value,
|
||||||
|
curve=secp256k1
|
||||||
|
)
|
||||||
|
|
||||||
|
def __rmul__(self, scalar: int) -> "Point":
|
||||||
|
|
||||||
|
current = self
|
||||||
|
result = I
|
||||||
|
while scalar:
|
||||||
|
if scalar & 1:
|
||||||
|
result = result + current
|
||||||
|
current = current + current
|
||||||
|
scalar >>= 1
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Signature:
|
||||||
|
r: int
|
||||||
|
s: int
|
||||||
|
|
||||||
|
def verify(self, z: int, pub_key: Point) -> bool:
|
||||||
|
s_inv = pow(self.s, -1, N)
|
||||||
|
u = (z * s_inv) % N
|
||||||
|
v = (self.r * s_inv) % N
|
||||||
|
|
||||||
|
return (u*G + v*pub_key).x.value == self.r
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PrivateKey:
|
||||||
|
secret: int
|
||||||
|
|
||||||
|
def sign(self, z: int) -> Signature:
|
||||||
|
e = self.secret
|
||||||
|
k = randint(0, N)
|
||||||
|
R = k * G
|
||||||
|
r = R.x.value
|
||||||
|
k_inv = pow(k, -1, N)
|
||||||
|
s = ((z + r*e) * k_inv) % N
|
||||||
|
|
||||||
|
return Signature(r, s)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
|
||||||
|
A = 0
|
||||||
|
B = 7
|
||||||
|
|
||||||
|
field = PrimeGaloisField(prime=P)
|
||||||
|
secp256k1 = EllipticCurve(a=A, b=B, field=field)
|
||||||
|
|
||||||
|
G = Point(
|
||||||
|
x=0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
|
||||||
|
y=0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8,
|
||||||
|
curve=secp256k1)
|
||||||
|
|
||||||
|
N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
|
||||||
|
|
||||||
|
I = Point(x=None, y=None, curve=secp256k1)
|
||||||
|
|
||||||
|
inf = float("inf")
|
||||||
|
|
||||||
|
priv: int = 0xea11d6ada978a0b491aa5cbbe4df17a65c2fecc24448e95d1ccd854b43991bec
|
||||||
|
e = PrivateKey(priv)
|
||||||
|
|
||||||
|
pub = e.secret * G
|
||||||
|
print(pub)
|
||||||
|
z = 0x7e240de74fb1ed08fa08d38063f6a6a91462a815
|
||||||
|
|
||||||
|
signature: Signature = e.sign(z)
|
||||||
|
print(e.sign(z))
|
||||||
|
assert signature.verify(z, pub)
|
|
@ -0,0 +1,114 @@
|
||||||
|
class prince:
|
||||||
|
def __init__(self, inL: list, inK: list):
|
||||||
|
self.SBox = [0x0B, 0x0F, 0x03, 0x02, 0x0A, 0x0C, 0x09, 0x01, 0x06, 0x07, 0x08, 0x00, 0x0E, 0x05, 0x0D, 0x04]
|
||||||
|
self.InvSBox = [0x0B, 0x07, 0x03, 0x02, 0x0F, 0x0D, 0x08, 0x09, 0x0A, 0x06, 0x04, 0x00, 0x05, 0x0E, 0x0C, 0x01]
|
||||||
|
|
||||||
|
self.RC = [
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x31, 0x91, 0xa8, 0xe2, 0x30, 0x07, 0x37, 0x44,
|
||||||
|
0x4a, 0x90, 0x83, 0x22, 0x92, 0xf9, 0x13, 0x0d,
|
||||||
|
0x80, 0xe2, 0xaf, 0x89, 0xce, 0xe4, 0xc6, 0x98
|
||||||
|
]
|
||||||
|
|
||||||
|
self._plaintext = inL
|
||||||
|
self.Key = inK
|
||||||
|
|
||||||
|
def cipher(self, ExKey):
|
||||||
|
|
||||||
|
self._plaintext = [self._plaintext[i] ^ ExKey[i] for i in range(8)]
|
||||||
|
|
||||||
|
self._AddKey(ExKey)
|
||||||
|
self._RCLayer(0)
|
||||||
|
|
||||||
|
|
||||||
|
self._SLayer()
|
||||||
|
self._MLayer()
|
||||||
|
self._RCLayer(1)
|
||||||
|
self._AddKey(ExKey)
|
||||||
|
|
||||||
|
self._SLayer()
|
||||||
|
self._MPrimeLayer()
|
||||||
|
self._InvSLayer()
|
||||||
|
|
||||||
|
self._AddKey(ExKey)
|
||||||
|
self._RCLayer(2)
|
||||||
|
self._InvMLayer()
|
||||||
|
self._InvSLayer()
|
||||||
|
|
||||||
|
self._RCLayer(3)
|
||||||
|
self._AddKey(ExKey)
|
||||||
|
|
||||||
|
self._plaintext = [self._plaintext[i] ^ ExKey[i+8] for i in range(8)]
|
||||||
|
|
||||||
|
def ExtendKey(self, Key):
|
||||||
|
newKey = [0x00] * 24
|
||||||
|
|
||||||
|
for i in range(8):
|
||||||
|
newKey[i] = Key[i]
|
||||||
|
newKey[i + 8] = (Key[i] >> 1) | (Key[(i + 1) % 8] << 7 & 0x80)
|
||||||
|
newKey[i + 16] = Key[i + 8]
|
||||||
|
|
||||||
|
newKey[15] ^= (Key[7] & 0x10)
|
||||||
|
|
||||||
|
return newKey
|
||||||
|
|
||||||
|
def _SR(self):
|
||||||
|
temp = self._plaintext[:]
|
||||||
|
perm = [0, 5, 2, 7, 4, 1, 6, 3]
|
||||||
|
|
||||||
|
self._plaintext = [ (temp[perm[i]] & 0x0F) | (self._plaintext[perm[(i+2)%8]] & 0xF0) for i in range(8)]
|
||||||
|
|
||||||
|
|
||||||
|
def _InvSR(self):
|
||||||
|
temp = self._plaintext[:]
|
||||||
|
perm = [0, 5, 2, 7, 4, 1, 6, 3]
|
||||||
|
|
||||||
|
self._plaintext = [ (temp[perm[i]] & 0x0F) | (self._plaintext[perm[(i+6)%8]] & 0xF0) for i in range(8)]
|
||||||
|
|
||||||
|
def _SLayer(self):
|
||||||
|
self._plaintext = [ (self.SBox[self._plaintext[i] >> 4] << 4) | self.SBox[self._plaintext[i] & 0x0F] for i in range(8) ]
|
||||||
|
|
||||||
|
|
||||||
|
def _InvSLayer(self):
|
||||||
|
self._plaintext = [ (self.InvSBox[self._plaintext[i] >> 4] << 4) | self.InvSBox[self._plaintext[i] & 0x0F] for i in range(8) ]
|
||||||
|
|
||||||
|
def _MPrimeLayer(self):
|
||||||
|
temp = self._plaintext[0]
|
||||||
|
self._plaintext[0] = (temp & 0xD7) ^ (self._plaintext[1] & 0x7D) ^ (temp >> 4 & 0x0B) ^ (self._plaintext[1] >> 4 & 0x0E) ^ (temp << 4 & 0xB0) ^ (self._plaintext[1] << 4 & 0xE0)
|
||||||
|
self._plaintext[1] = (temp & 0x7D) ^ (self._plaintext[1] & 0xD7) ^ (temp >> 4 & 0x0E) ^ (self._plaintext[1] >> 4 & 0x0B) ^ (temp << 4 & 0xE0) ^ (self._plaintext[1] << 4 & 0xB0)
|
||||||
|
temp = self._plaintext[2]
|
||||||
|
self._plaintext[2] = (temp & 0xEB) ^ (self._plaintext[3] & 0xBE) ^ (temp >> 4 & 0x0D) ^ (self._plaintext[3] >> 4 & 0x07) ^ (temp << 4 & 0xD0) ^ (self._plaintext[3] << 4 & 0x70)
|
||||||
|
self._plaintext[3] = (temp & 0xBE) ^ (self._plaintext[3] & 0xEB) ^ (temp >> 4 & 0x07) ^ (self._plaintext[3] >> 4 & 0x0D) ^ (temp << 4 & 0x70) ^ (self._plaintext[3] << 4 & 0xD0)
|
||||||
|
temp = self._plaintext[4]
|
||||||
|
self._plaintext[4] = (temp & 0xEB) ^ (self._plaintext[5] & 0xBE) ^ (temp >> 4 & 0x0D) ^ (self._plaintext[5] >> 4 & 0x07) ^ (temp << 4 & 0xD0) ^ (self._plaintext[5] << 4 & 0x70)
|
||||||
|
self._plaintext[5] = (temp & 0xBE) ^ (self._plaintext[5] & 0xEB) ^ (temp >> 4 & 0x07) ^ (self._plaintext[5] >> 4 & 0x0D) ^ (temp << 4 & 0x70) ^ (self._plaintext[5] << 4 & 0xD0)
|
||||||
|
temp = self._plaintext[6]
|
||||||
|
self._plaintext[6] = (temp & 0xD7) ^ (self._plaintext[7] & 0x7D) ^ (temp >> 4 & 0x0B) ^ (self._plaintext[7] >> 4 & 0x0E) ^ (temp << 4 & 0xB0) ^ (self._plaintext[7] << 4 & 0xE0)
|
||||||
|
self._plaintext[7] = (temp & 0x7D) ^ (self._plaintext[7] & 0xD7) ^ (temp >> 4 & 0x0E) ^ (self._plaintext[7] >> 4 & 0x0B) ^ (temp << 4 & 0xE0) ^ (self._plaintext[7] << 4 & 0xB0)
|
||||||
|
|
||||||
|
def _MLayer(self):
|
||||||
|
self._MPrimeLayer()
|
||||||
|
self._SR()
|
||||||
|
|
||||||
|
def _InvMLayer(self):
|
||||||
|
self._InvSR()
|
||||||
|
self._MPrimeLayer()
|
||||||
|
|
||||||
|
def _RCLayer(self, round):
|
||||||
|
self._plaintext = [ self._plaintext[i] ^ self.RC[8 * round + i] for i in range(8)]
|
||||||
|
|
||||||
|
def _AddKey(self, ExKey):
|
||||||
|
self._plaintext = [ self._plaintext[i] ^ ExKey[i + 16] for i in range(8) ]
|
||||||
|
|
||||||
|
def prince(self):
|
||||||
|
ExKey = self.ExtendKey(self.Key)
|
||||||
|
self.cipher(ExKey)
|
||||||
|
return [nibble >> 4 | (nibble << 4 & 0xF0) for nibble in self._plaintext]
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
ExKey = self.ExtendKey(self.Key)
|
||||||
|
self.cipher(ExKey)
|
||||||
|
print('0x', end='')
|
||||||
|
for i in range(8):
|
||||||
|
print(format(self._plaintext[i] >> 4 | (self._plaintext[i] << 4 & 0xF0), '02x'), end='')
|
||||||
|
print()
|
|
@ -0,0 +1,142 @@
|
||||||
|
|
||||||
|
|
||||||
|
SBox = [0x0B, 0x0F, 0x03, 0x02, 0x0A, 0x0C, 0x09, 0x01, 0x06, 0x07, 0x08, 0x00, 0x0E, 0x05, 0x0D, 0x04]
|
||||||
|
# Inverse substitution box used on individual nibbles
|
||||||
|
InvSBox = [0x0B, 0x07, 0x03, 0x02, 0x0F, 0x0D, 0x08, 0x09, 0x0A, 0x06, 0x04, 0x00, 0x05, 0x0E, 0x0C, 0x01]
|
||||||
|
|
||||||
|
RC = [
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x31, 0x91, 0xa8, 0xe2, 0x30, 0x07, 0x37, 0x44,
|
||||||
|
0x4a, 0x90, 0x83, 0x22, 0x92, 0xf9, 0x13, 0x0d,
|
||||||
|
0x80, 0xe2, 0xaf, 0x89, 0xce, 0xe4, 0xc6, 0x98
|
||||||
|
]
|
||||||
|
|
||||||
|
_State = [0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE]
|
||||||
|
Key = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01]
|
||||||
|
|
||||||
|
def cipher(ExtendedKey):
|
||||||
|
""" The complete PRINCE forward encryption on the 64-bit state performed through nibble calculations """
|
||||||
|
global _State
|
||||||
|
|
||||||
|
_State = [_State[i] ^ ExtendedKey[i] for i in range(8)]
|
||||||
|
|
||||||
|
_AddKey(ExtendedKey)
|
||||||
|
_AddRoundConstant(0)
|
||||||
|
|
||||||
|
|
||||||
|
_SubNibbles()
|
||||||
|
_MLayer()
|
||||||
|
_AddRoundConstant(1)
|
||||||
|
_AddKey(ExtendedKey)
|
||||||
|
|
||||||
|
_SubNibbles()
|
||||||
|
_MPrimeLayer()
|
||||||
|
_InvSubNibbles()
|
||||||
|
|
||||||
|
_AddKey(ExtendedKey)
|
||||||
|
_AddRoundConstant(2)
|
||||||
|
_InvMLayer()
|
||||||
|
_InvSubNibbles()
|
||||||
|
|
||||||
|
_AddRoundConstant(3)
|
||||||
|
_AddKey(ExtendedKey)
|
||||||
|
|
||||||
|
_State = [_State[i] ^ ExtendedKey[i+8] for i in range(8)]
|
||||||
|
|
||||||
|
def ExtendKey(Key):
|
||||||
|
""" PRINCE's version of a key schedule, which extends our 128-bit key to a 192-bit key """
|
||||||
|
newKey = [0x00] * 24
|
||||||
|
|
||||||
|
for i in range(8):
|
||||||
|
# k_0 stays the same
|
||||||
|
newKey[i] = Key[i]
|
||||||
|
# k'_0 is a k_0 rotated right one bit and XORed with the last bit
|
||||||
|
newKey[i + 8] = (Key[i] >> 1) | (Key[(i + 1) % 8] << 7 & 0x80)
|
||||||
|
# k_1 stays the same
|
||||||
|
newKey[i + 16] = Key[i + 8]
|
||||||
|
|
||||||
|
newKey[15] ^= (Key[7] & 0x10)
|
||||||
|
|
||||||
|
return newKey
|
||||||
|
|
||||||
|
def _ShiftRows():
|
||||||
|
""" Helper method which distinguishes our two linear layers M from M' """
|
||||||
|
global _State
|
||||||
|
|
||||||
|
temp = _State[:] # copy the state into a temporary holder
|
||||||
|
perm = [0, 5, 2, 7, 4, 1, 6, 3]
|
||||||
|
|
||||||
|
_State = [ (temp[perm[i]] & 0x0F) | (_State[perm[(i+2)%8]] & 0xF0) for i in range(8)]
|
||||||
|
|
||||||
|
|
||||||
|
def _InvShiftRows():
|
||||||
|
""" Inverse of our ShiftRows() function which allows us to distinguish M'^-1 from M^-1 """
|
||||||
|
global _State
|
||||||
|
|
||||||
|
temp = _State[:] # copy the state into a temporary holder
|
||||||
|
perm = [0, 5, 2, 7, 4, 1, 6, 3]
|
||||||
|
|
||||||
|
_State = [ (temp[perm[i]] & 0x0F) | (_State[perm[(i+6)%8]] & 0xF0) for i in range(8)]
|
||||||
|
|
||||||
|
|
||||||
|
def _SubNibbles():
|
||||||
|
""" Send the state through a substitution layer nibble-by-nibble """
|
||||||
|
global _State
|
||||||
|
_State = [ (SBox[_State[i] >> 4] << 4) | SBox[_State[i] & 0x0F] for i in range(8) ]
|
||||||
|
|
||||||
|
|
||||||
|
def _InvSubNibbles():
|
||||||
|
""" Inverse of our substitution layer which sends each substituted nibble back to the original nibble """
|
||||||
|
global _State
|
||||||
|
_State = [ (InvSBox[_State[i] >> 4] << 4) | InvSBox[_State[i] & 0x0F] for i in range(8) ]
|
||||||
|
|
||||||
|
|
||||||
|
def _MPrimeLayer():
|
||||||
|
""" Our linear layer, designed to use as little space as possible and prevent wasted clock-cycles. Recall that this method is in fact its own inverse. """
|
||||||
|
global _State
|
||||||
|
|
||||||
|
# M0
|
||||||
|
temp = _State[0] # we only need 1 storage variable here
|
||||||
|
_State[0] = (temp & 0xD7) ^ (_State[1] & 0x7D) ^ (temp >> 4 & 0x0B) ^ (_State[1] >> 4 & 0x0E) ^ (temp << 4 & 0xB0) ^ (_State[1] << 4 & 0xE0)
|
||||||
|
_State[1] = (temp & 0x7D) ^ (_State[1] & 0xD7) ^ (temp >> 4 & 0x0E) ^ (_State[1] >> 4 & 0x0B) ^ (temp << 4 & 0xE0) ^ (_State[1] << 4 & 0xB0)
|
||||||
|
# M1
|
||||||
|
temp = _State[2]
|
||||||
|
_State[2] = (temp & 0xEB) ^ (_State[3] & 0xBE) ^ (temp >> 4 & 0x0D) ^ (_State[3] >> 4 & 0x07) ^ (temp << 4 & 0xD0) ^ (_State[3] << 4 & 0x70)
|
||||||
|
_State[3] = (temp & 0xBE) ^ (_State[3] & 0xEB) ^ (temp >> 4 & 0x07) ^ (_State[3] >> 4 & 0x0D) ^ (temp << 4 & 0x70) ^ (_State[3] << 4 & 0xD0)
|
||||||
|
# M1
|
||||||
|
temp = _State[4]
|
||||||
|
_State[4] = (temp & 0xEB) ^ (_State[5] & 0xBE) ^ (temp >> 4 & 0x0D) ^ (_State[5] >> 4 & 0x07) ^ (temp << 4 & 0xD0) ^ (_State[5] << 4 & 0x70)
|
||||||
|
_State[5] = (temp & 0xBE) ^ (_State[5] & 0xEB) ^ (temp >> 4 & 0x07) ^ (_State[5] >> 4 & 0x0D) ^ (temp << 4 & 0x70) ^ (_State[5] << 4 & 0xD0)
|
||||||
|
# M0
|
||||||
|
temp = _State[6]
|
||||||
|
_State[6] = (temp & 0xD7) ^ (_State[7] & 0x7D) ^ (temp >> 4 & 0x0B) ^ (_State[7] >> 4 & 0x0E) ^ (temp << 4 & 0xB0) ^ (_State[7] << 4 & 0xE0)
|
||||||
|
_State[7] = (temp & 0x7D) ^ (_State[7] & 0xD7) ^ (temp >> 4 & 0x0E) ^ (_State[7] >> 4 & 0x0B) ^ (temp << 4 & 0xE0) ^ (_State[7] << 4 & 0xB0)
|
||||||
|
|
||||||
|
def _MLayer():
|
||||||
|
""" The adjusted linear layer which is utilized each regular round """
|
||||||
|
_MPrimeLayer()
|
||||||
|
_ShiftRows()
|
||||||
|
|
||||||
|
def _InvMLayer():
|
||||||
|
""" The inverse adjusted linear layer which is utilized each inverse regular round """
|
||||||
|
_InvShiftRows()
|
||||||
|
_MPrimeLayer()
|
||||||
|
|
||||||
|
def _AddRoundConstant(round):
|
||||||
|
""" Function which simply applies a given round's constant to the state """
|
||||||
|
global _State
|
||||||
|
_State = [ _State[i] ^ RC[8 * round + i] for i in range(8)]
|
||||||
|
|
||||||
|
def _AddKey(ExtendedKey):
|
||||||
|
""" Function which adds k_1 to the state """
|
||||||
|
global _State
|
||||||
|
_State = [ _State[i] ^ ExtendedKey[i + 16] for i in range(8) ]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
ExtendedKey = ExtendKey(Key)
|
||||||
|
cipher(ExtendedKey)
|
||||||
|
print('0x', end='')
|
||||||
|
for i in range(8):
|
||||||
|
print(format(_State[i] >> 4 | (_State[i] << 4 & 0xF0), '02x'), end='')
|
||||||
|
print()
|
|
@ -0,0 +1,25 @@
|
||||||
|
G = Point(
|
||||||
|
x=0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
|
||||||
|
y=0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8,
|
||||||
|
curve=secp256k1)
|
||||||
|
|
||||||
|
N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
|
||||||
|
|
||||||
|
I = Point(x=None, y=None, curve=secp256k1)
|
||||||
|
|
||||||
|
assert N * G == I
|
||||||
|
|
||||||
|
pub = Point(
|
||||||
|
x=0x9577FF57C8234558F293DF502CA4F09CBC65A6572C842B39B366F21717945116,
|
||||||
|
y=0x10B49C67FA9365AD7B90DAB070BE339A1DAF9052373EC30FFAE4F72D5E66D053,
|
||||||
|
curve=secp256k1
|
||||||
|
)
|
||||||
|
d: int = 2 ** 240 + 2 ** 31
|
||||||
|
print(d * G)
|
||||||
|
print(pub)
|
||||||
|
|
||||||
|
e = PrivateKey(randint(0, N))
|
||||||
|
pub = e.secret * G
|
||||||
|
z = randint(0, 2 ** 256)
|
||||||
|
signature: Signature = e.sign(z)
|
||||||
|
assert signature.verify(z, pub)
|
|
@ -0,0 +1,175 @@
|
||||||
|
|
||||||
|
|
||||||
|
SBox = [0x0B, 0x0F, 0x03, 0x02, 0x0A, 0x0C, 0x09, 0x01, 0x06, 0x07, 0x08, 0x00, 0x0E, 0x05, 0x0D, 0x04]
|
||||||
|
# Inverse substitution box used on individual nibbles
|
||||||
|
InvSBox = [0x0B, 0x07, 0x03, 0x02, 0x0F, 0x0D, 0x08, 0x09, 0x0A, 0x06, 0x04, 0x00, 0x05, 0x0E, 0x0C, 0x01]
|
||||||
|
|
||||||
|
RC = [
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x31, 0x91, 0xa8, 0xe2, 0x30, 0x07, 0x37, 0x44,
|
||||||
|
0x4a, 0x90, 0x83, 0x22, 0x92, 0xf9, 0x13, 0x0d,
|
||||||
|
0x80, 0xe2, 0xaf, 0x89, 0xce, 0xe4, 0xc6, 0x98
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def cipher(ExtendedKey):
|
||||||
|
""" The complete PRINCE forward encryption on the 64-bit state performed through nibble calculations """
|
||||||
|
global _State
|
||||||
|
|
||||||
|
_State = [_State[i] ^ ExtendedKey[i] for i in range(8)]
|
||||||
|
|
||||||
|
_AddKey(ExtendedKey)
|
||||||
|
_AddRoundConstant(0)
|
||||||
|
|
||||||
|
|
||||||
|
_SubNibbles()
|
||||||
|
_MLayer()
|
||||||
|
_AddRoundConstant(1)
|
||||||
|
_AddKey(ExtendedKey)
|
||||||
|
|
||||||
|
_SubNibbles()
|
||||||
|
_MPrimeLayer()
|
||||||
|
_InvSubNibbles()
|
||||||
|
|
||||||
|
_AddKey(ExtendedKey)
|
||||||
|
_AddRoundConstant(2)
|
||||||
|
_InvMLayer()
|
||||||
|
_InvSubNibbles()
|
||||||
|
|
||||||
|
_AddRoundConstant(3)
|
||||||
|
_AddKey(ExtendedKey)
|
||||||
|
|
||||||
|
_State = [_State[i] ^ ExtendedKey[i+8] for i in range(8)]
|
||||||
|
|
||||||
|
def ExtendKey(Key):
|
||||||
|
""" PRINCE's version of a key schedule, which extends our 128-bit key to a 192-bit key """
|
||||||
|
newKey = [0x00] * 24
|
||||||
|
|
||||||
|
for i in range(8):
|
||||||
|
# k_0 stays the same
|
||||||
|
newKey[i] = Key[i]
|
||||||
|
# k'_0 is a k_0 rotated right one bit and XORed with the last bit
|
||||||
|
newKey[i + 8] = (Key[i] >> 1) | (Key[(i + 1) % 8] << 7 & 0x80)
|
||||||
|
# k_1 stays the same
|
||||||
|
newKey[i + 16] = Key[i + 8]
|
||||||
|
|
||||||
|
newKey[15] ^= (Key[7] & 0x10)
|
||||||
|
|
||||||
|
return newKey
|
||||||
|
|
||||||
|
def _ShiftRows():
|
||||||
|
""" Helper method which distinguishes our two linear layers M from M' """
|
||||||
|
global _State
|
||||||
|
|
||||||
|
temp = _State[:] # copy the state into a temporary holder
|
||||||
|
perm = [0, 5, 2, 7, 4, 1, 6, 3]
|
||||||
|
|
||||||
|
_State = [ (temp[perm[i]] & 0x0F) | (_State[perm[(i+2)%8]] & 0xF0) for i in range(8)]
|
||||||
|
|
||||||
|
|
||||||
|
def _InvShiftRows():
|
||||||
|
""" Inverse of our ShiftRows() function which allows us to distinguish M'^-1 from M^-1 """
|
||||||
|
global _State
|
||||||
|
|
||||||
|
temp = _State[:] # copy the state into a temporary holder
|
||||||
|
perm = [0, 5, 2, 7, 4, 1, 6, 3]
|
||||||
|
|
||||||
|
_State = [ (temp[perm[i]] & 0x0F) | (_State[perm[(i+6)%8]] & 0xF0) for i in range(8)]
|
||||||
|
|
||||||
|
|
||||||
|
def _SubNibbles():
|
||||||
|
""" Send the state through a substitution layer nibble-by-nibble """
|
||||||
|
global _State
|
||||||
|
_State = [ (SBox[_State[i] >> 4] << 4) | SBox[_State[i] & 0x0F] for i in range(8) ]
|
||||||
|
|
||||||
|
|
||||||
|
def _InvSubNibbles():
|
||||||
|
""" Inverse of our substitution layer which sends each substituted nibble back to the original nibble """
|
||||||
|
global _State
|
||||||
|
_State = [ (InvSBox[_State[i] >> 4] << 4) | InvSBox[_State[i] & 0x0F] for i in range(8) ]
|
||||||
|
|
||||||
|
|
||||||
|
def _MPrimeLayer():
|
||||||
|
""" Our linear layer, designed to use as little space as possible and prevent wasted clock-cycles. Recall that this method is in fact its own inverse. """
|
||||||
|
global _State
|
||||||
|
|
||||||
|
# M0
|
||||||
|
temp = _State[0] # we only need 1 storage variable here
|
||||||
|
_State[0] = (temp & 0xD7) ^ (_State[1] & 0x7D) ^ (temp >> 4 & 0x0B) ^ (_State[1] >> 4 & 0x0E) ^ (temp << 4 & 0xB0) ^ (_State[1] << 4 & 0xE0)
|
||||||
|
_State[1] = (temp & 0x7D) ^ (_State[1] & 0xD7) ^ (temp >> 4 & 0x0E) ^ (_State[1] >> 4 & 0x0B) ^ (temp << 4 & 0xE0) ^ (_State[1] << 4 & 0xB0)
|
||||||
|
# M1
|
||||||
|
temp = _State[2]
|
||||||
|
_State[2] = (temp & 0xEB) ^ (_State[3] & 0xBE) ^ (temp >> 4 & 0x0D) ^ (_State[3] >> 4 & 0x07) ^ (temp << 4 & 0xD0) ^ (_State[3] << 4 & 0x70)
|
||||||
|
_State[3] = (temp & 0xBE) ^ (_State[3] & 0xEB) ^ (temp >> 4 & 0x07) ^ (_State[3] >> 4 & 0x0D) ^ (temp << 4 & 0x70) ^ (_State[3] << 4 & 0xD0)
|
||||||
|
# M1
|
||||||
|
temp = _State[4]
|
||||||
|
_State[4] = (temp & 0xEB) ^ (_State[5] & 0xBE) ^ (temp >> 4 & 0x0D) ^ (_State[5] >> 4 & 0x07) ^ (temp << 4 & 0xD0) ^ (_State[5] << 4 & 0x70)
|
||||||
|
_State[5] = (temp & 0xBE) ^ (_State[5] & 0xEB) ^ (temp >> 4 & 0x07) ^ (_State[5] >> 4 & 0x0D) ^ (temp << 4 & 0x70) ^ (_State[5] << 4 & 0xD0)
|
||||||
|
# M0
|
||||||
|
temp = _State[6]
|
||||||
|
_State[6] = (temp & 0xD7) ^ (_State[7] & 0x7D) ^ (temp >> 4 & 0x0B) ^ (_State[7] >> 4 & 0x0E) ^ (temp << 4 & 0xB0) ^ (_State[7] << 4 & 0xE0)
|
||||||
|
_State[7] = (temp & 0x7D) ^ (_State[7] & 0xD7) ^ (temp >> 4 & 0x0E) ^ (_State[7] >> 4 & 0x0B) ^ (temp << 4 & 0xE0) ^ (_State[7] << 4 & 0xB0)
|
||||||
|
|
||||||
|
def _MLayer():
|
||||||
|
""" The adjusted linear layer which is utilized each regular round """
|
||||||
|
_MPrimeLayer()
|
||||||
|
_ShiftRows()
|
||||||
|
|
||||||
|
def _InvMLayer():
|
||||||
|
""" The inverse adjusted linear layer which is utilized each inverse regular round """
|
||||||
|
_InvShiftRows()
|
||||||
|
_MPrimeLayer()
|
||||||
|
|
||||||
|
def _AddRoundConstant(round):
|
||||||
|
""" Function which simply applies a given round's constant to the state """
|
||||||
|
global _State
|
||||||
|
_State = [ _State[i] ^ RC[8 * round + i] for i in range(8)]
|
||||||
|
|
||||||
|
def _AddKey(ExtendedKey):
|
||||||
|
""" Function which adds k_1 to the state """
|
||||||
|
global _State
|
||||||
|
_State = [ _State[i] ^ ExtendedKey[i + 16] for i in range(8) ]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# _State = [0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE]
|
||||||
|
# Key = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01]
|
||||||
|
|
||||||
|
# ExtendedKey = ExtendKey(Key)
|
||||||
|
# cipher(ExtendedKey)
|
||||||
|
# print('0x', end='')
|
||||||
|
# for i in range(8):
|
||||||
|
# print(format(_State[i] >> 4 | (_State[i] << 4 & 0xF0), '02x'), end='')
|
||||||
|
# print()
|
||||||
|
|
||||||
|
plainfile = open("pt.dat", "rb")
|
||||||
|
cipherfile = open("ct.dat", "rb")
|
||||||
|
|
||||||
|
key = []
|
||||||
|
for i in range(16):
|
||||||
|
key.append(bytearray(8))
|
||||||
|
|
||||||
|
active = [15,14,13,12,11]
|
||||||
|
for t in range(5):
|
||||||
|
# for each SET
|
||||||
|
A = []
|
||||||
|
for i in range(16):
|
||||||
|
A.append(bytearray(16))
|
||||||
|
|
||||||
|
for j in range(t*16,(t+1)*16):
|
||||||
|
pbyte = plainfile.read(8)
|
||||||
|
cbyte = cipherfile.read(8)
|
||||||
|
pbytearay = [((a&0x0F)<<4)|((a&0xF0)>>4) for a in list(pbyte)][::-1]
|
||||||
|
cbytearay = [((a&0x0F)<<4)|((a&0xF0)>>4) for a in list(cbyte)][::-1]
|
||||||
|
nibarray = []
|
||||||
|
for dibble in [(str(hex(i))).replace('0x','') for i in cbytearay]:
|
||||||
|
dibble = dibble.zfill(2)
|
||||||
|
nibarray.append(dibble[0])
|
||||||
|
nibarray.append(dibble[1])
|
||||||
|
|
||||||
|
for i in range(16):
|
||||||
|
x = int('0x'+str(nibarray[i]),16)
|
||||||
|
A[i][x] = 1
|
||||||
|
|
||||||
|
for i in range(16):
|
||||||
|
print([[a[0:4],a[4:8],a[8:12],a[12:16]] for a in A])
|
Loading…
Reference in New Issue