in scram/aes_scram.py [0:0]
def scram_encrypt(K, N, A, M, F):
"""
SCRAM Encryption
Parameters:
K: Key
N: Nonce
A: Additional Authenticated Data
M: Plaintext Message
F: Frame Size
Returns:
C: Ciphertext
X: Excrypted R and Padding Len
Tag: Authentication Tag
"""
# Generate a random 32-byte value R
R = rndfile.read(32)
# Prepare the Padding. We append 0x00 bytes to the end up to the next frame size.
M_LEN = len(M)
PADDING_LEN = 0
if (F > 0):
PADDING_LEN = (F - M_LEN) % F
PADDING_STR = byteStr(0x0, PADDING_LEN)
PADDING_LEN_STR = byteStr(PADDING_LEN, 2)
PADDED_MSG = M + PADDING_STR
debugInt("len(M)", M_LEN)
debugInt("PADDING_LEN", PADDING_LEN)
debugByteStr("PADDING_STR", PADDING_STR)
debugByteStr("PADDING_LEN_STR", PADDING_LEN_STR)
debugByteStr("PADDED_MSG", PADDED_MSG)
# Derive Message encryption key (KE)
# S1 = N || 0x00 0x00 0x00 0x1 || 0^{8} || 0^{8} || 0^{16} || R
S1 = N + byteStr(0x01, 4) + byteStr(0x0, 8) + byteStr(0x0, 8) + byteStr(0x0, 16) + R
U1 = hmac.new(K, S1, hashlib.sha512).digest()
KE = U1[0:32]
# AES_CTR encrypt PADDED_MSG with Nonce N and Key KE
C = AES.new(key=KE, mode=AES.MODE_CTR, nonce=N).encrypt(PADDED_MSG)
# Derive MAC Key (KM) used to with GMAC to generate T
# S2 = N || 0x00 0x00 0x00 0x2 || 0^{8} || 0^{8} || 0^{16} || 0^{32}
S2 = N + byteStr(0x02, 4) + byteStr(0x0, 8) + byteStr(0x0, 8) + byteStr(0x0, 16) + byteStr(0x0, 32)
U2 = hmac.new(K, S2, hashlib.sha512).digest()
KM = U2[0:32]
# GMAC the string A || C , using the GMAC key KM and nonce N
T = AES.new(key=KM, mode=AES.MODE_GCM, nonce=N).update(A + C).digest()
# Derive a one-time pad (U3) from T
# S3 = N || 0x00 0x00 0x00 0x3 || 0^{8} || 0^{8} || T || 0^{32}
S3 = N + byteStr(0x03, 4) + byteStr(0x0, 8) + byteStr(0x0, 8) + T + byteStr(0x0, 32)
U3 = hmac.new(K, S3, hashlib.sha512).digest()
# Encrypt R and PaddingLen with one-time pad U3
Y1 = bytes(a ^ b for (a, b) in zip(U3[0:32], R))
Y0 = bytes(a ^ b for (a, b) in zip(U3[32:34], PADDING_LEN_STR))
X = Y1 + Y0
# Authenticate (Tag) T and R
# S4 = N || 0x00 0x00 0x00 0x4 || A_LEN_STR || M_LEN_STR || T || R
S4 = N + byteStr(0x04, 4) + byteStr(len(A), 8) + byteStr(M_LEN, 8) + T + R
U4 = hmac.new(K, S4, hashlib.sha512).digest()
# Truncate to 16 bytes tag
Tag = U4[0:16]
debugByteStr("S1", S1)
debugByteStr("S2", S2)
debugByteStr("S3", S3)
debugByteStr("S4", S4)
debugByteStr("U1", U1)
debugByteStr("U2", U2)
debugByteStr("U3", U3)
debugByteStr("U4", U4)
debugByteStr("Y0", Y0)
debugByteStr("Y1", Y1)
debugByteStr("T", T)
debugByteStr("KE", KE)
debugByteStr("KM", KM)
debugInt("len(C)", len(C))
debugByteStr("C", C)
debugByteStr("X", X)
debugByteStr("Tag", Tag)
return C, X, Tag