From 3498f276191ab9a1037ccdbcbdf49d59e818f305 Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Fri, 25 Jul 2025 00:06:40 +0900 Subject: [PATCH] Implement HIGHT algorithm with official test vector (TEST PASSED) #293 Implement HIGHT algorithm with official test vector (TEST PASSED) #293 --- .../WelsonJS.Cryptography.Test/Program.vb | 4 +- .../WelsonJS.Cryptography/HightCore.vb | 242 +++++++++++------- .../HightEcbTransform.vb | 7 +- 3 files changed, 160 insertions(+), 93 deletions(-) diff --git a/WelsonJS.Toolkit/WelsonJS.Cryptography.Test/Program.vb b/WelsonJS.Toolkit/WelsonJS.Cryptography.Test/Program.vb index c712760..fb1fad3 100644 --- a/WelsonJS.Toolkit/WelsonJS.Cryptography.Test/Program.vb +++ b/WelsonJS.Toolkit/WelsonJS.Cryptography.Test/Program.vb @@ -33,7 +33,7 @@ Module Program ' HIGHT algorithm Console.WriteLine("Start HIGHT encryption and decryption test") Dim hightCipher As New WelsonJS.Cryptography.HightAlgorithm() - hightCipher.Key = {&H0, &H11, &H22, &H33, &H44, &H55, &H66, &H77, &H88, &H99, &HAA, &HBB, &HCC, &HDD, &HEE, &HFF} + hightCipher.Key = {&H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0} ' hightCipher.IV = {&H0F, &H1E, &H2D, &H3C, &H4B, &H5A, &H69, &H78, &H87, &H96, &HA5, &HB4, &HC3, &HD2, &HE1, &HF0} hightCipher.Mode = CipherMode.ECB hightCipher.Padding = PaddingMode.PKCS7 @@ -45,7 +45,7 @@ Module Program Public Sub RunTest(cipher As SymmetricAlgorithm) ' Dim inputBytes As Byte() = {&H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0, &HFE} ' SEED test vector ' Dim inputBytes As Byte() = {&H11, &H11, &H11, &H11, &HAA, &HAA, &HAA, &HAA, &H11, &H11, &H11, &H11, &HBB, &HBB, &HBB, &HBB} ' ARIA test vector - Dim inputBytes As Byte() = {&H0, &H0, &H0, &H0, &H0, &H0, &H0, &H0} ' HIGHT test vector + Dim inputBytes As Byte() = {&H80, &H0, &H0, &H0, &H0, &H0, &H0, &H0} ' HIGHT test vector Console.WriteLine("Key (HEX):") PrintHex(cipher.Key) diff --git a/WelsonJS.Toolkit/WelsonJS.Cryptography/HightCore.vb b/WelsonJS.Toolkit/WelsonJS.Cryptography/HightCore.vb index 5bb666c..01fec35 100644 --- a/WelsonJS.Toolkit/WelsonJS.Cryptography/HightCore.vb +++ b/WelsonJS.Toolkit/WelsonJS.Cryptography/HightCore.vb @@ -1,6 +1,11 @@ -Public Class HightCore +' HightCore.cs (WelsonJS.Cryptography) +' SPDX-License-Identifier: MIT +' SPDX-FileCopyrightText: 2025 Namhyeon Go , Catswords OSS And WelsonJS Contributors +' https://github.com/gnh1201/welsonjs +' +Public Class HightCore Private ReadOnly roundKey(135) As Byte - Private Shared ReadOnly Delta As Byte() = { + Private Shared ReadOnly DELTA As Byte() = { &H5A, &H6D, &H36, &H1B, &HD, &H6, &H3, &H41, &H60, &H30, &H18, &H4C, &H66, &H33, &H59, &H2C, &H56, &H2B, &H15, &H4A, &H65, &H72, &H39, &H1C, @@ -19,121 +24,178 @@ &H74, &H3A, &H5D, &H2E, &H57, &H6B, &H35, &H5A } + Private Shared ReadOnly F0_TABLE As Byte() = { + &H0, &H86, &HD, &H8B, &H1A, &H9C, &H17, &H91, &H34, &HB2, &H39, &HBF, &H2E, &HA8, &H23, &HA5, + &H68, &HEE, &H65, &HE3, &H72, &HF4, &H7F, &HF9, &H5C, &HDA, &H51, &HD7, &H46, &HC0, &H4B, &HCD, + &HD0, &H56, &HDD, &H5B, &HCA, &H4C, &HC7, &H41, &HE4, &H62, &HE9, &H6F, &HFE, &H78, &HF3, &H75, + &HB8, &H3E, &HB5, &H33, &HA2, &H24, &HAF, &H29, &H8C, &HA, &H81, &H7, &H96, &H10, &H9B, &H1D, + &HA1, &H27, &HAC, &H2A, &HBB, &H3D, &HB6, &H30, &H95, &H13, &H98, &H1E, &H8F, &H9, &H82, &H4, + &HC9, &H4F, &HC4, &H42, &HD3, &H55, &HDE, &H58, &HFD, &H7B, &HF0, &H76, &HE7, &H61, &HEA, &H6C, + &H71, &HF7, &H7C, &HFA, &H6B, &HED, &H66, &HE0, &H45, &HC3, &H48, &HCE, &H5F, &HD9, &H52, &HD4, + &H19, &H9F, &H14, &H92, &H3, &H85, &HE, &H88, &H2D, &HAB, &H20, &HA6, &H37, &HB1, &H3A, &HBC, + &H43, &HC5, &H4E, &HC8, &H59, &HDF, &H54, &HD2, &H77, &HF1, &H7A, &HFC, &H6D, &HEB, &H60, &HE6, + &H2B, &HAD, &H26, &HA0, &H31, &HB7, &H3C, &HBA, &H1F, &H99, &H12, &H94, &H5, &H83, &H8, &H8E, + &H93, &H15, &H9E, &H18, &H89, &HF, &H84, &H2, &HA7, &H21, &HAA, &H2C, &HBD, &H3B, &HB0, &H36, + &HFB, &H7D, &HF6, &H70, &HE1, &H67, &HEC, &H6A, &HCF, &H49, &HC2, &H44, &HD5, &H53, &HD8, &H5E, + &HE2, &H64, &HEF, &H69, &HF8, &H7E, &HF5, &H73, &HD6, &H50, &HDB, &H5D, &HCC, &H4A, &HC1, &H47, + &H8A, &HC, &H87, &H1, &H90, &H16, &H9D, &H1B, &HBE, &H38, &HB3, &H35, &HA4, &H22, &HA9, &H2F, + &H32, &HB4, &H3F, &HB9, &H28, &HAE, &H25, &HA3, &H6, &H80, &HB, &H8D, &H1C, &H9A, &H11, &H97, + &H5A, &HDC, &H57, &HD1, &H40, &HC6, &H4D, &HCB, &H6E, &HE8, &H63, &HE5, &H74, &HF2, &H79, &HFF + } + + Private Shared ReadOnly F1_TABLE As Byte() = { + &H0, &H58, &HB0, &HE8, &H61, &H39, &HD1, &H89, &HC2, &H9A, &H72, &H2A, &HA3, &HFB, &H13, &H4B, + &H85, &HDD, &H35, &H6D, &HE4, &HBC, &H54, &HC, &H47, &H1F, &HF7, &HAF, &H26, &H7E, &H96, &HCE, + &HB, &H53, &HBB, &HE3, &H6A, &H32, &HDA, &H82, &HC9, &H91, &H79, &H21, &HA8, &HF0, &H18, &H40, + &H8E, &HD6, &H3E, &H66, &HEF, &HB7, &H5F, &H7, &H4C, &H14, &HFC, &HA4, &H2D, &H75, &H9D, &HC5, + &H16, &H4E, &HA6, &HFE, &H77, &H2F, &HC7, &H9F, &HD4, &H8C, &H64, &H3C, &HB5, &HED, &H5D, &H5D, + &H93, &HCB, &H23, &H7B, &HF2, &HAA, &H42, &H1A, &H51, &H9, &HE1, &HB9, &H30, &H68, &H80, &HD8, + &H1D, &H45, &HAD, &HF5, &H7C, &H24, &HCC, &H94, &HDF, &H87, &H6F, &H37, &HBE, &HE6, &HE, &H56, + &H98, &HC0, &H28, &H70, &HF9, &HA1, &H49, &H11, &H5A, &H2, &HEA, &HB2, &H3B, &H63, &H8B, &HD3, + &H2C, &H74, &H9C, &HC4, &H4D, &H15, &HFD, &HA5, &HEE, &HB6, &H5E, &H6, &H8F, &HD7, &H3F, &H67, + &HA9, &HF1, &H19, &H41, &HC8, &H90, &H78, &H20, &H6B, &H33, &HDB, &H83, &HA, &H52, &HBA, &HE2, + &H27, &H7F, &H97, &HCF, &H46, &H1E, &HF6, &HAE, &HE5, &HBD, &H55, &HD, &H84, &HDC, &H34, &H6C, + &HA2, &HFA, &H12, &H4A, &HC3, &H9B, &H73, &H2B, &H60, &H38, &HD0, &H88, &H1, &H59, &HB1, &HE9, + &H3A, &H62, &H8A, &HD2, &H5B, &H3, &HEB, &HB3, &HF8, &HA0, &H48, &H10, &H99, &HC1, &H29, &H71, + &HBF, &HE7, &HF, &H57, &HDE, &H86, &H6E, &H36, &H7D, &H25, &HCD, &H95, &H1C, &H44, &HAC, &HF4, + &H31, &H69, &H81, &HD9, &H50, &H8, &HE0, &HB8, &HF3, &HAB, &H43, &H1B, &H92, &HCA, &H22, &H7A, + &HB4, &HEC, &H4, &H5C, &HD5, &H8D, &H65, &H3D, &H76, &H2E, &HC6, &H9E, &H17, &H4F, &HA7, &HFF + } + Public Sub New(userKey As Byte()) If userKey.Length <> 16 Then Throw New ArgumentException("Key must be 16 bytes") KeySchedule(userKey) End Sub - Private Sub KeySchedule(userKey As Byte()) - ' Whitening keys - For i As Integer = 0 To 3 - roundKey(i) = userKey(i + 12) - roundKey(i + 4) = userKey(i) + Private Function F0(x As Byte) As Byte + Return F0_TABLE(x) + End Function + + Private Function F1(x As Byte) As Byte + Return F1_TABLE(x) + End Function + + Private Function Mod8(x As Integer) As Integer + Return ((x Mod 8) + 8) Mod 8 + End Function + + Private Sub KeySchedule(key As Byte()) + If key.Length <> 16 Then Throw New ArgumentException("Key must be 16 bytes") + + ' 1. Set the whitening key (WK0 ~ WK7): Use MK[8..15] + For i As Integer = 0 To 7 + roundKey(i) = key(8 + i) Next - ' Round keys (SK008 to SK135) + ' 2. Set the round key (key length is 128) For i As Integer = 0 To 7 For j As Integer = 0 To 7 Dim idx = 16 * i + j - roundKey(8 + idx) = CByte((userKey((j - i) And 7) + Delta(idx)) And &HFF) - roundKey(8 + idx + 8) = CByte((userKey(8 + ((j - i) And 7)) + Delta(idx + 8)) And &HFF) + roundKey(8 + idx) = CByte((key(8 + Mod8(j - i)) + DELTA(idx)) And &HFF) + roundKey(8 + idx + 8) = CByte((key(Mod8(j - i)) + DELTA(idx + 8)) And &HFF) Next Next End Sub - Private Function RotL(x As Byte, n As Integer) As Byte - Return CByte(((x << n) Or (x >> (8 - n))) And &HFF) - End Function - - Private Function F0(x As Byte) As Byte - Return CByte(RotL(x, 1) Xor RotL(x, 2) Xor RotL(x, 7)) - End Function - - Private Function F1(x As Byte) As Byte - Return CByte(RotL(x, 3) Xor RotL(x, 4) Xor RotL(x, 6)) - End Function - Public Sub EncryptBlock(input() As Byte, inOffset As Integer, output() As Byte, outOffset As Integer) - Dim X(7) As Byte - ' Initial whitening - X(0) = CByte((input(inOffset + 0) + roundKey(0)) And &HFF) - X(1) = input(inOffset + 1) - X(2) = CByte(input(inOffset + 2) Xor roundKey(1)) - X(3) = input(inOffset + 3) - X(4) = CByte((input(inOffset + 4) + roundKey(2)) And &HFF) - X(5) = input(inOffset + 5) - X(6) = CByte(input(inOffset + 6) Xor roundKey(3)) - X(7) = input(inOffset + 7) + Dim XX(7) As Byte - For r As Integer = 0 To 31 - Dim T0 = CByte(F0(X(1)) Xor roundKey(8 + 4 * r + 0)) - Dim T1 = CByte(F1(X(3)) Xor roundKey(8 + 4 * r + 1)) - Dim T2 = CByte(F0(X(5)) Xor roundKey(8 + 4 * r + 2)) - Dim T3 = CByte(F1(X(7)) Xor roundKey(8 + 4 * r + 3)) + ' First Round + XX(1) = input(inOffset + 1) + XX(3) = input(inOffset + 3) + XX(5) = input(inOffset + 5) + XX(7) = input(inOffset + 7) - Dim tmp(7) As Byte - tmp(0) = X(1) - tmp(1) = CByte((X(2) + T0) And &HFF) - tmp(2) = X(3) - tmp(3) = CByte((X(0) + T1) And &HFF) - tmp(4) = X(5) - tmp(5) = CByte((X(6) + T2) And &HFF) - tmp(6) = X(7) - tmp(7) = CByte((X(4) + T3) And &HFF) + XX(0) = CByte((input(inOffset + 0) + roundKey(0)) And &HFF) + XX(2) = CByte(input(inOffset + 2) Xor roundKey(1)) + XX(4) = CByte((input(inOffset + 4) + roundKey(2)) And &HFF) + XX(6) = CByte(input(inOffset + 6) Xor roundKey(3)) - Array.Copy(tmp, X, 8) + Dim HIGHT_ENC As Action(Of Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer) = + Sub(k, i0, i1, i2, i3, i4, i5, i6, i7) + XX(i0) = CByte((XX(i0) Xor (F0(XX(i1)) + roundKey(4 * k + 3))) And &HFF) + XX(i2) = CByte((XX(i2) + (F1(XX(i3)) Xor roundKey(4 * k + 2))) And &HFF) + XX(i4) = CByte((XX(i4) Xor (F0(XX(i5)) + roundKey(4 * k + 1))) And &HFF) + XX(i6) = CByte((XX(i6) + (F1(XX(i7)) Xor roundKey(4 * k + 0))) And &HFF) + End Sub + + Dim encRounds As Integer()() = { + New Integer() {7, 6, 5, 4, 3, 2, 1, 0}, + New Integer() {6, 5, 4, 3, 2, 1, 0, 7}, + New Integer() {5, 4, 3, 2, 1, 0, 7, 6}, + New Integer() {4, 3, 2, 1, 0, 7, 6, 5}, + New Integer() {3, 2, 1, 0, 7, 6, 5, 4}, + New Integer() {2, 1, 0, 7, 6, 5, 4, 3}, + New Integer() {1, 0, 7, 6, 5, 4, 3, 2}, + New Integer() {0, 7, 6, 5, 4, 3, 2, 1} + } + + For round As Integer = 2 To 33 + Dim seq As Integer() = encRounds((round - 2) Mod 8) + HIGHT_ENC(round, seq(0), seq(1), seq(2), seq(3), seq(4), seq(5), seq(6), seq(7)) Next - ' Final whitening - output(outOffset + 0) = CByte((X(0) + roundKey(4)) And &HFF) - output(outOffset + 1) = X(1) - output(outOffset + 2) = CByte(X(2) Xor roundKey(5)) - output(outOffset + 3) = X(3) - output(outOffset + 4) = CByte((X(4) + roundKey(6)) And &HFF) - output(outOffset + 5) = X(5) - output(outOffset + 6) = CByte(X(6) Xor roundKey(7)) - output(outOffset + 7) = X(7) + output(outOffset + 1) = XX(2) + output(outOffset + 3) = XX(4) + output(outOffset + 5) = XX(6) + output(outOffset + 7) = XX(0) + + output(outOffset + 0) = CByte((XX(1) + roundKey(4)) And &HFF) + output(outOffset + 2) = CByte(XX(3) Xor roundKey(5)) + output(outOffset + 4) = CByte((XX(5) + roundKey(6)) And &HFF) + output(outOffset + 6) = CByte(XX(7) Xor roundKey(7)) End Sub Public Sub DecryptBlock(input() As Byte, inOffset As Integer, output() As Byte, outOffset As Integer) - Dim X(7) As Byte - ' Final whitening undo - X(0) = CByte((input(inOffset + 0) - roundKey(4)) And &HFF) - X(1) = input(inOffset + 1) - X(2) = CByte(input(inOffset + 2) Xor roundKey(5)) - X(3) = input(inOffset + 3) - X(4) = CByte((input(inOffset + 4) - roundKey(6)) And &HFF) - X(5) = input(inOffset + 5) - X(6) = CByte(input(inOffset + 6) Xor roundKey(7)) - X(7) = input(inOffset + 7) + Dim XX(7) As Byte - For r As Integer = 31 To 0 Step -1 - Dim T3 = CByte(F1(X(6)) Xor roundKey(8 + 4 * r + 3)) - Dim T2 = CByte(F0(X(4)) Xor roundKey(8 + 4 * r + 2)) - Dim T1 = CByte(F1(X(2)) Xor roundKey(8 + 4 * r + 1)) - Dim T0 = CByte(F0(X(0)) Xor roundKey(8 + 4 * r + 0)) + ' Initial Round + XX(2) = input(inOffset + 1) + XX(4) = input(inOffset + 3) + XX(6) = input(inOffset + 5) + XX(0) = input(inOffset + 7) - Dim tmp(7) As Byte - tmp(0) = CByte((X(3) - T1) And &HFF) - tmp(1) = X(0) - tmp(2) = CByte((X(1) - T0) And &HFF) - tmp(3) = X(2) - tmp(4) = CByte((X(7) - T3) And &HFF) - tmp(5) = X(4) - tmp(6) = CByte((X(5) - T2) And &HFF) - tmp(7) = X(6) + XX(1) = CByte((input(inOffset + 0) - roundKey(4)) And &HFF) + XX(3) = CByte(input(inOffset + 2) Xor roundKey(5)) + XX(5) = CByte((input(inOffset + 4) - roundKey(6)) And &HFF) + XX(7) = CByte(input(inOffset + 6) Xor roundKey(7)) - Array.Copy(tmp, X, 8) + ' HIGHT_DEC as Action + Dim HIGHT_DEC As Action(Of Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer, Integer) = + Sub(k, i0, i1, i2, i3, i4, i5, i6, i7) + XX(i1) = CByte((XX(i1) - (F1(XX(i2)) Xor roundKey(4 * k + 2))) And &HFF) + XX(i3) = CByte((XX(i3) Xor (F0(XX(i4)) + roundKey(4 * k + 1))) And &HFF) + XX(i5) = CByte((XX(i5) - (F1(XX(i6)) Xor roundKey(4 * k + 0))) And &HFF) + XX(i7) = CByte((XX(i7) Xor (F0(XX(i0)) + roundKey(4 * k + 3))) And &HFF) + End Sub + + ' Round pattern (same as encryption, reused) + Dim decRounds As Integer()() = { + New Integer() {7, 6, 5, 4, 3, 2, 1, 0}, + New Integer() {0, 7, 6, 5, 4, 3, 2, 1}, + New Integer() {1, 0, 7, 6, 5, 4, 3, 2}, + New Integer() {2, 1, 0, 7, 6, 5, 4, 3}, + New Integer() {3, 2, 1, 0, 7, 6, 5, 4}, + New Integer() {4, 3, 2, 1, 0, 7, 6, 5}, + New Integer() {5, 4, 3, 2, 1, 0, 7, 6}, + New Integer() {6, 5, 4, 3, 2, 1, 0, 7} + } + + ' Apply decryption rounds + For round As Integer = 33 To 2 Step -1 + Dim seq As Integer() = decRounds((33 - round) Mod 8) + HIGHT_DEC(round, seq(0), seq(1), seq(2), seq(3), seq(4), seq(5), seq(6), seq(7)) Next - ' Initial whitening undo - output(outOffset + 0) = CByte((X(0) - roundKey(0)) And &HFF) - output(outOffset + 1) = X(1) - output(outOffset + 2) = CByte(X(2) Xor roundKey(1)) - output(outOffset + 3) = X(3) - output(outOffset + 4) = CByte((X(4) - roundKey(2)) And &HFF) - output(outOffset + 5) = X(5) - output(outOffset + 6) = CByte(X(6) Xor roundKey(3)) - output(outOffset + 7) = X(7) + ' Final output + output(outOffset + 1) = XX(1) + output(outOffset + 3) = XX(3) + output(outOffset + 5) = XX(5) + output(outOffset + 7) = XX(7) + + output(outOffset + 0) = CByte((XX(0) - roundKey(0)) And &HFF) + output(outOffset + 2) = CByte(XX(2) Xor roundKey(1)) + output(outOffset + 4) = CByte((XX(4) - roundKey(2)) And &HFF) + output(outOffset + 6) = CByte(XX(6) Xor roundKey(3)) End Sub End Class diff --git a/WelsonJS.Toolkit/WelsonJS.Cryptography/HightEcbTransform.vb b/WelsonJS.Toolkit/WelsonJS.Cryptography/HightEcbTransform.vb index 40a215a..68adea9 100644 --- a/WelsonJS.Toolkit/WelsonJS.Cryptography/HightEcbTransform.vb +++ b/WelsonJS.Toolkit/WelsonJS.Cryptography/HightEcbTransform.vb @@ -1,4 +1,9 @@ -Imports System.Security.Cryptography +' HightEcbTransform.cs (WelsonJS.Cryptography) +' SPDX-License-Identifier: MIT +' SPDX-FileCopyrightText: 2025 Namhyeon Go , Catswords OSS And WelsonJS Contributors +' https://github.com/gnh1201/welsonjs +' +Imports System.Security.Cryptography Public Class HightEcbTransform Implements ICryptoTransform