forked from Telos4/LoRa-Workshop
76 lines
1.8 KiB
Python
76 lines
1.8 KiB
Python
|
from struct import pack, unpack
|
||
|
import ucryptolib
|
||
|
MODE_ECB = 1
|
||
|
|
||
|
|
||
|
class AES_CMAC:
|
||
|
def gen_subkey(self, K):
|
||
|
AES_128 = ucryptolib.aes(bytearray(K), MODE_ECB)
|
||
|
|
||
|
L = AES_128.encrypt(('\x00'*16).encode())
|
||
|
|
||
|
LHigh = unpack('>Q',L[:8])[0]
|
||
|
LLow = unpack('>Q',L[8:])[0]
|
||
|
|
||
|
K1High = ((LHigh << 1) | ( LLow >> 63 )) & 0xFFFFFFFFFFFFFFFF
|
||
|
K1Low = (LLow << 1) & 0xFFFFFFFFFFFFFFFF
|
||
|
|
||
|
if (LHigh >> 63):
|
||
|
K1Low ^= 0x87
|
||
|
|
||
|
K2High = ((K1High << 1) | (K1Low >> 63)) & 0xFFFFFFFFFFFFFFFF
|
||
|
K2Low = ((K1Low << 1)) & 0xFFFFFFFFFFFFFFFF
|
||
|
|
||
|
if (K1High >> 63):
|
||
|
K2Low ^= 0x87
|
||
|
|
||
|
K1 = pack('>QQ', K1High, K1Low)
|
||
|
K2 = pack('>QQ', K2High, K2Low)
|
||
|
|
||
|
return K1, K2
|
||
|
|
||
|
def xor_128(self, N1, N2):
|
||
|
J = b''
|
||
|
for i in range(len(N1)):
|
||
|
J += bytes([N1[i] ^ N2[i]])
|
||
|
return J
|
||
|
|
||
|
def pad(self, N):
|
||
|
const_Bsize = 16
|
||
|
padLen = 16-len(N)
|
||
|
return N + b'\x80' + b'\x00'*(padLen-1)
|
||
|
|
||
|
def encode(self, K, M):
|
||
|
const_Bsize = 16
|
||
|
const_Zero = b'\x00'*16
|
||
|
|
||
|
AES_128 = ucryptolib.aes(bytearray(K), MODE_ECB)
|
||
|
|
||
|
K1, K2 = self.gen_subkey(K)
|
||
|
n = int(len(M)/const_Bsize)
|
||
|
|
||
|
if n == 0:
|
||
|
n = 1
|
||
|
flag = False
|
||
|
else:
|
||
|
if (len(M) % const_Bsize) == 0:
|
||
|
flag = True
|
||
|
else:
|
||
|
n += 1
|
||
|
flag = False
|
||
|
|
||
|
M_n = M[(n-1)*const_Bsize:]
|
||
|
if flag is True:
|
||
|
M_last = self.xor_128(M_n,K1)
|
||
|
else:
|
||
|
M_last = self.xor_128(self.pad(M_n),K2)
|
||
|
|
||
|
X = const_Zero
|
||
|
for i in range(n-1):
|
||
|
M_i = M[(i)*const_Bsize:][:16]
|
||
|
Y = self.xor_128(X, M_i)
|
||
|
X = AES_128.encrypt(Y)
|
||
|
Y = self.xor_128(M_last, X)
|
||
|
T = AES_128.encrypt(Y)
|
||
|
return T
|