/*
* Copyright (c) Huawei Technologies Co., Ltd. 2022-2024. All rights reserved.
*/
package zip4cj.crypto.engine
let S: Array<Byte> = [99, 124, 119, 123, 242, 107, 111, 197,
48, 1, 103, 43, 254, 215, 171, 118,
202, 130, 201, 125, 250, 89, 71, 240,
173, 212, 162, 175, 156, 164, 114, 192,
183, 253, 147, 38, 54, 63, 247, 204,
52, 165, 229, 241, 113, 216, 49, 21,
4, 199, 35, 195, 24, 150, 5, 154,
7, 18, 128, 226, 235, 39, 178, 117,
9, 131, 44, 26, 27, 110, 90, 160,
82, 59, 214, 179, 41, 227, 47, 132,
83, 209, 0, 237, 32, 252, 177, 91,
106, 203, 190, 57, 74, 76, 88, 207,
208, 239, 170, 251, 67, 77, 51, 133,
69, 249, 2, 127, 80, 60, 159, 168,
81, 163, 64, 143, 146, 157, 56, 245,
188, 182, 218, 33, 16, 255, 243, 210,
205, 12, 19, 236, 95, 151, 68, 23,
196, 167, 126, 61, 100, 93, 25, 115,
96, 129, 79, 220, 34, 42, 144, 136,
70, 238, 184, 20, 222, 94, 11, 219,
224, 50, 58, 10, 73, 6, 36, 92,
194, 211, 172, 98, 145, 149, 228, 121,
231, 200, 55, 109, 141, 213, 78, 169,
108, 86, 244, 234, 101, 122, 174, 8,
186, 120, 37, 46, 28, 166, 180, 198,
232, 221, 116, 31, 75, 189, 139, 138,
112, 62, 181, 102, 72, 3, 246, 14,
97, 53, 87, 185, 134, 193, 29, 158,
225, 248, 152, 17, 105, 217, 142, 148,
155, 30, 135, 233, 206, 85, 40, 223,
140, 161, 137, 13, 191, 230, 66, 104,
65, 153, 45, 15, 176, 84, 187, 22]
let rcon: Array<Int32> = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91]
let T0: Array<Int32> = [-1520213050, -2072216328, -1720223762, -1921287178, 234025727, -1117033514, -1318096930,
1422247313, 1345335392, 50397442, -1452841010, 2099981142, 436141799, 1658312629, -424957107, -1703512340, 1170918031,
-1652391393, 1086966153, -2021818886, 368769775, -346465870, -918075506, 200339707, -324162239, 1742001331, -39673249,
-357585083, -1080255453, -140204973, -1770884380, 1539358875, -1028147339, 486407649, -1366060227, 1780885068,
1513502316, 1094664062, 49805301, 1338821763, 1546925160, -190470831, 887481809, 150073849, -1821281822, 1943591083,
1395732834, 1058346282, 201589768, 1388824469, 1696801606, 1589887901, 672667696, -1583966665, 251987210, -1248159185,
151455502, 907153956, -1686077413, 1038279391, 652995533, 1764173646, -843926913, -1619692054, 453576978, -1635548387,
1949051992, 773462580, 756751158, -1301385508, -296068428, -73359269, -162377052, 1295727478, 1641469623, -827083907,
2066295122, 1055122397, 1898917726, -1752923117, -179088474, 1758581177, 0, 753790401, 1612718144, 536673507,
-927878791, -312779850, -1100322092, 1187761037, -641810841, 1262041458, -565556588, -733197160, -396863312, 1255133061,
1808847035, 720367557, -441800113, 385612781, -985447546, -682799718, 1429418854, -1803188975, -817543798, 284817897,
100794884, -2122350594, -263171936, 1144798328, -1163944155, -475486133, -212774494, -22830243, -1069531008,
-1970303227, -1382903233, -1130521311, 1211644016, 83228145, -541279133, -1044990345, 1977277103, 1663115586, 806359072,
452984805, 250868733, 1842533055, 1288555905, 336333848, 890442534, 804056259, -513843266, -1567123659, -867941240,
957814574, 1472513171, -223893675, -2105639172, 1195195770, -1402706744, -413311558, 723065138, -1787595802,
-1604296512, -1736343271, -783331426, 2145180835, 1713513028, 2116692564, -1416589253, -2088204277, -901364084,
703524551, -742868885, 1007948840, 2044649127, -497131844, 487262998, 1994120109, 1004593371, 1446130276, 1312438900,
503974420, -615954030, 168166924, 1814307912, -463709000, 1573044895, 1859376061, -273896381, -1503501628, -1466855111,
-1533700815, 937747667, -1954973198, 854058965, 1137232011, 1496790894, -1217565222, -1936880383, 1691735473,
-766620004, -525751991, -1267962664, -95005012, 133494003, 636152527, -1352309302, -1904575756, -374428089, 403179536,
-709182865, -2005370640, 1864705354, 1915629148, 605822008, -240736681, -944458637, 1371981463, 602466507, 2094914977,
-1670089496, 555687742, -582268010, -591544991, -2037675251, -2054518257, -1871679264, 1111375484, -994724495,
-1436129588, -666351472, 84083462, 32962295, 302911004, -1553899070, 1597322602, -111716434, -793134743, -1853454825,
1489093017, 656219450, -1180787161, 954327513, 335083755, -1281845205, 856756514, -1150719534, 1893325225, -1987146233,
-1483434957, -1231316179, 572399164, -1836611819, 552200649, 1238290055, -11184726, 2015897680, 2061492133, -1886614525,
-123625127, -2138470135, 386731290, -624967835, 837215959, -968736124, -1201116976, -1019133566, -1332111063,
1999449434, 286199582, -877612933, -61582168, -692339859, 974525996]
func subWord(x: Int32): Int32 {
return (Int32(S[Int64(x & 255)]) & 255 |
(((Int32(S[Int64((x >> 8) & 255)])) & 255) << 8) |
((Int32(S[Int64((x >> 16) & 255)]) & 255) << 16) |
Int32(S[Int64((x >> 24) & 255)]) << 24)
}
func shift(r: Int32, shift: Int64): Int32 {
return (r[shift]) | (r << (32-shift))
}
/**
* Core Engine for AES Encryption
*
* @author Srikanth Reddy Lingala
*/
public class AESEngine {
private var rounds: Int64 = 0
private var workingKey: Array<Array<Int32>> = unsafe { zeroValue<Array<Array<Int32>>>() }
private var C0: Int32 = 0
private var C1: Int32 = 0
private var C2: Int32 = 0
private var C3: Int32 = 0
public init(key: Array<Byte>) {
workingKey = generateWorkingKey(key)
}
func generateWorkingKey(key: Array<UInt8>): Array<Array<Int32>> {
var kc: Int64 = key.size / 4
var t: Int64
if (((kc != 4) && (kc != 6) && (kc != 8)) || ((kc * 4) != key.size)) {
throw ZipException("invalid key length (not 128/192/256)")
}
rounds = kc + 6
var W = Array<Array<Int32>>(Int64(rounds + 1), {i => Array<Int32>(4, repeat: 0)})
t = 0
var i = 0
while (i < key.size) {
W[t >> 2][t & 3] = (Int32(key[i]) & 0xff) | ((Int32(key[i + 1]) & 0xff) << 8) | ((Int32(key[i + 2]) & 0xff) <<
16) | (Int32(key[i + 3]) << 24)
i += 4
t++
}
for (i in kc..(Int64(rounds + 1) << 2)) {
var temp = W[(i - 1) >> 2][(i - 1) & 3]
if ((i % kc) == 0) {
temp = subWord(shift(temp, 8)) ^ rcon[(i / kc) - 1]
} else if ((kc > 6) && ((i % kc) == 4)) {
temp = subWord(temp)
}
W[i >> 2][i & 3] = W[(i - kc) >> 2][(i - kc) & 3] ^ temp
}
return W
}
public func processBlock(input: Array<UInt8>, out: Array<UInt8>): Int64 {
return processBlock(input, 0, out, 0)
}
public func processBlock(input: Array<UInt8>, inOff: Int64, out: Array<UInt8>, outOff: Int64): Int64 {
if ((inOff + (32 / 2)) > input.size) {
throw ZipException("input buffer too short")
}
if ((outOff + (32 / 2)) > out.size) {
throw ZipException("output buffer too short")
}
stateIn(input, inOff)
encryptBlock(workingKey)
stateOut(out, outOff)
return InternalZipConstants.AES_BLOCK_SIZE
}
private func stateIn(bytes: Array<UInt8>, off: Int64) {
var index = off
C0 = (Int32(bytes[index]) & 0xff)
index++
C0 |= (Int32(bytes[index]) & 0xff) << 8
index++
C0 |= (Int32(bytes[index]) & 0xff) << 16
index++
C0 |= Int32(bytes[index]) << 24
index++
C1 = (Int32(bytes[index]) & 0xff)
index++
C1 |= (Int32(bytes[index]) & 0xff) << 8
index++
C1 |= (Int32(bytes[index]) & 0xff) << 16
index++
C1 |= Int32(bytes[index]) << 24
index++
C2 = (Int32(bytes[index]) & 0xff)
index++
C2 |= (Int32(bytes[index]) & 0xff) << 8
index++
C2 |= (Int32(bytes[index]) & 0xff) << 16
index++
C2 |= Int32(bytes[index]) << 24
index++
C3 = (Int32(bytes[index]) & 0xff)
index++
C3 |= (Int32(bytes[index]) & 0xff) << 8
index++
C3 |= (Int32(bytes[index]) & 0xff) << 16
index++
C3 |= Int32(bytes[index]) << 24
}
@OverflowWrapping
private func stateOut(bytes: Array<UInt8>, off: Int64) {
var index = off
bytes[index] = UInt8(C0)
index++
bytes[index] = UInt8(C0 >> 8)
index++
bytes[index] = UInt8(C0 >> 16)
index++
bytes[index] = UInt8(C0 >> 24)
index++
bytes[index] = UInt8(C1)
index++
bytes[index] = UInt8(C1 >> 8)
index++
bytes[index] = UInt8(C1 >> 16)
index++
bytes[index] = UInt8(C1 >> 24)
index++
bytes[index] = UInt8(C2)
index++
bytes[index] = UInt8(C2 >> 8)
index++
bytes[index] = UInt8(C2 >> 16)
index++
bytes[index] = UInt8(C2 >> 24)
index++
bytes[index] = UInt8(C3)
index++
bytes[index] = UInt8(C3 >> 8)
index++
bytes[index] = UInt8(C3 >> 16)
index++
bytes[index] = UInt8(C3 >> 24)
}
private func encryptBlock(KW: Array<Array<Int32>>) {
var r = 0
var r0: Int32 = 0
var r1: Int32 = 0
var r2: Int32 = 0
var r3: Int32 = 0
C0 = (Int32(C0) ^ KW[0][0])
C1 = (Int32(C1) ^ KW[0][1])
C2 = (Int32(C2) ^ KW[0][2])
C3 = (Int32(C3) ^ KW[0][3])
r = 1
while (r < rounds - 1) {
r0 = T0[Int64(C0 & 255)] ^ shift(T0[Int64((C1 >> 8) & 255)], 24) ^ shift(T0[Int64((C2 >> 16) & 255)], 16) ^ shift(T0[Int64((C3 >> 24) & 255)], 8) ^ KW[r][0]
r1 = T0[Int64(C1 & 255)] ^ shift(T0[Int64((C2 >> 8) & 255)], 24) ^ shift(T0[Int64((C3 >> 16) & 255)], 16) ^ shift(T0[Int64((C0 >> 24) & 255)], 8) ^ KW[r][1]
r2 = T0[Int64(C2 & 255)] ^ shift(T0[Int64((C3 >> 8) & 255)], 24) ^ shift(T0[Int64((C0 >> 16) & 255)], 16) ^ shift(T0[Int64((C1 >> 24) & 255)], 8) ^ KW[r][2]
r3 = T0[Int64(C3 & 255)] ^ shift(T0[Int64((C0 >> 8) & 255)], 24) ^ shift(T0[Int64((C1 >> 16) & 255)], 16) ^ shift(T0[Int64((C2 >> 24) & 255)], 8) ^ KW[r][3]
r++
C0 = T0[Int64(r0 & 255)] ^ shift(T0[Int64((r1 >> 8) & 255)], 24) ^ shift(T0[Int64((r2 >> 16) & 255)], 16) ^ shift(T0[Int64((r3 >> 24) & 255)], 8) ^ KW[r][0]
C1 = T0[Int64(r1 & 255)] ^ shift(T0[Int64((r2 >> 8) & 255)], 24) ^ shift(T0[Int64((r3 >> 16) & 255)], 16) ^ shift(T0[Int64((r0 >> 24) & 255)], 8) ^ KW[r][1]
C2 = T0[Int64(r2 & 255)] ^ shift(T0[Int64((r3 >> 8) & 255)], 24) ^ shift(T0[Int64((r0 >> 16) & 255)], 16) ^ shift(T0[Int64((r1 >> 24) & 255)], 8) ^ KW[r][2]
C3 = T0[Int64(r3 & 255)] ^ shift(T0[Int64((r0 >> 8) & 255)], 24) ^ shift(T0[Int64((r1 >> 16) & 255)], 16) ^ shift(T0[Int64((r2 >> 24) & 255)], 8) ^ KW[r][3]
r++
}
r0 = T0[Int64(C0 & 255)] ^ shift(T0[Int64((C1 >> 8) & 255)], 24) ^ shift(T0[Int64((C2 >> 16) & 255)], 16) ^ shift(T0[Int64((C3 >> 24) & 255)], 8) ^ KW[r][0]
r1 = T0[Int64(C1 & 255)] ^ shift(T0[Int64((C2 >> 8) & 255)], 24) ^ shift(T0[Int64((C3 >> 16) & 255)], 16) ^ shift(T0[Int64((C0 >> 24) & 255)], 8) ^ KW[r][1]
r2 = T0[Int64(C2 & 255)] ^ shift(T0[Int64((C3 >> 8) & 255)], 24) ^ shift(T0[Int64((C0 >> 16) & 255)], 16) ^ shift(T0[Int64((C1 >> 24) & 255)], 8) ^ KW[r][2]
r3 = T0[Int64(C3 & 255)] ^ shift(T0[Int64((C0 >> 8) & 255)], 24) ^ shift(T0[Int64((C1 >> 16) & 255)], 16) ^ shift(T0[Int64((C2 >> 24) & 255)], 8) ^ KW[r][3]
r++
C0 = (Int32(S[Int64(r0 & 255)]) & 255) ^ ((Int32(S[Int64((r1 >> 8) & 255)]) & 255) << 8) ^ ((Int32(S[Int64((r2 >> 16) & 255)]) & 255) << 16) ^ (Int32(S[Int64((r3 >> 24) & 255)]) << 24) ^ KW[r][0]
C1 = (Int32(S[Int64(r1 & 255)]) & 255) ^ ((Int32(S[Int64((r2 >> 8) & 255)]) & 255) << 8) ^ ((Int32(S[Int64((r3 >> 16) & 255)]) & 255) << 16) ^ (Int32(S[Int64((r0 >> 24) & 255)]) << 24) ^ KW[r][1]
C2 = (Int32(S[Int64(r2 & 255)]) & 255) ^ ((Int32(S[Int64((r3 >> 8) & 255)]) & 255) << 8) ^ ((Int32(S[Int64((r0 >> 16) & 255)]) & 255) << 16) ^ (Int32(S[Int64((r1 >> 24) & 255)]) << 24) ^ KW[r][2]
C3 = (Int32(S[Int64(r3 & 255)]) & 255) ^ ((Int32(S[Int64((r0 >> 8) & 255)]) & 255) << 8) ^ ((Int32(S[Int64((r1 >> 16) & 255)]) & 255) << 16) ^ (Int32(S[Int64((r2 >> 24) & 255)]) << 24) ^ KW[r][3]
}
}