Add HIGHT block cipher implementation #293

Implemented the HIGHT block cipher with ECB mode support, including HightAlgorithm, HightCore, and HightEcbTransform classes. Updated the test program to include HIGHT encryption/decryption tests and added support for PaddingMode.None in ARIA and SEED ECB transforms.
This commit is contained in:
Namhyeon Go 2025-07-20 19:49:52 +09:00
parent ec03bf415d
commit 2a8c4d196c
6 changed files with 371 additions and 3 deletions

View File

@ -30,12 +30,22 @@ Module Program
RunTest(ariaCipher)
Console.WriteLine()
' 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.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
RunTest(hightCipher)
Console.WriteLine()
End Sub
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}
Dim inputBytes As Byte() = {&H11, &H11, &H11, &H11, &HAA, &HAA, &HAA, &HAA, &H11, &H11, &H11, &H11, &HBB, &HBB, &HBB, &HBB}
' 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
Console.WriteLine("Key (HEX):")
PrintHex(cipher.Key)

View File

@ -70,6 +70,12 @@ Public Class AriaEcbTransform
Dim blockSize = InputBlockSize
Dim buffer() As Byte
If paddingMode = PaddingMode.None Then
buffer = New Byte(inputCount - 1) {}
TransformBlock(input, inputOffset, inputCount, buffer, 0)
Return buffer
End If
If encrypt Then
Dim paddedLength As Integer
Select Case paddingMode

View File

@ -0,0 +1,51 @@
Imports System.Security.Cryptography
Public Class HightAlgorithm
Inherits SymmetricAlgorithm
Public Sub New()
LegalBlockSizesValue = New KeySizes() {New KeySizes(64, 64, 0)}
LegalKeySizesValue = New KeySizes() {New KeySizes(128, 128, 0)}
Me.BlockSize = 64
Me.KeySize = 128
Me.FeedbackSize = 64
Me.Mode = CipherMode.ECB
Me.Padding = PaddingMode.PKCS7
Me.Key = New Byte(15) {}
Me.IV = New Byte(7) {}
End Sub
Public Overrides Sub GenerateKey()
Using rng As New RNGCryptoServiceProvider()
rng.GetBytes(Me.Key)
End Using
End Sub
Public Overrides Sub GenerateIV()
Using rng As New RNGCryptoServiceProvider()
rng.GetBytes(Me.IV)
End Using
End Sub
Public Overrides Function CreateEncryptor(rgbKey As Byte(), rgbIV As Byte()) As ICryptoTransform
Return CreateTransform(rgbKey, rgbIV, True)
End Function
Public Overrides Function CreateDecryptor(rgbKey As Byte(), rgbIV As Byte()) As ICryptoTransform
Return CreateTransform(rgbKey, rgbIV, False)
End Function
Private Function CreateTransform(key As Byte(), iv As Byte(), encrypt As Boolean) As ICryptoTransform
Select Case Me.Mode
Case CipherMode.ECB
Return New HightEcbTransform(key, encrypt, Me.Padding)
Case Else
Throw New NotSupportedException("This mode not supported yet")
End Select
End Function
' TODO: CCM, GCM, CMAC
End Class

View File

@ -0,0 +1,139 @@
Public Class HightCore
Private ReadOnly roundKey(135) 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,
&H4E, &H67, &H73, &H79, &H3C, &H5E, &H6F, &H37,
&H5B, &H2D, &H16, &HB, &H5, &H42, &H21, &H50,
&H28, &H54, &H2A, &H55, &H6A, &H75, &H7A, &H7D,
&H3E, &H5F, &H2F, &H17, &H4B, &H25, &H52, &H29,
&H14, &HA, &H45, &H62, &H31, &H58, &H6C, &H76,
&H3B, &H1D, &HE, &H47, &H63, &H71, &H78, &H7C,
&H7E, &H7F, &H3F, &H1F, &HF, &H7, &H43, &H61,
&H70, &H38, &H5C, &H6E, &H77, &H7B, &H3D, &H1E,
&H4F, &H27, &H53, &H69, &H34, &H1A, &H4D, &H26,
&H13, &H49, &H24, &H12, &H9, &H4, &H2, &H1,
&H40, &H20, &H10, &H8, &H44, &H22, &H11, &H48,
&H64, &H32, &H19, &HC, &H46, &H23, &H51, &H68,
&H74, &H3A, &H5D, &H2E, &H57, &H6B, &H35, &H5A
}
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)
Next
' Round keys (SK008 to SK135)
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)
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)
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))
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)
Array.Copy(tmp, X, 8)
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)
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)
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))
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)
Array.Copy(tmp, X, 8)
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)
End Sub
End Class

View File

@ -0,0 +1,156 @@
Imports System.Security.Cryptography
Public Class HightEcbTransform
Implements ICryptoTransform
Private ReadOnly rnd As New Random()
Private ReadOnly core As HightCore
Private ReadOnly encrypt As Boolean
Private ReadOnly paddingMode As PaddingMode
Public Sub New(key As Byte(), encryptMode As Boolean, Optional mode As PaddingMode = PaddingMode.PKCS7)
core = New HightCore(key)
encrypt = encryptMode
paddingMode = mode
End Sub
Public ReadOnly Property InputBlockSize As Integer Implements ICryptoTransform.InputBlockSize
Get
Return 8
End Get
End Property
Public ReadOnly Property OutputBlockSize As Integer Implements ICryptoTransform.OutputBlockSize
Get
Return 8
End Get
End Property
Public ReadOnly Property CanTransformMultipleBlocks As Boolean Implements ICryptoTransform.CanTransformMultipleBlocks
Get
Return True
End Get
End Property
Public ReadOnly Property CanReuseTransform As Boolean Implements ICryptoTransform.CanReuseTransform
Get
Return True
End Get
End Property
Public Function TransformBlock(input() As Byte, inputOffset As Integer, inputCount As Integer,
output() As Byte, outputOffset As Integer) As Integer Implements ICryptoTransform.TransformBlock
If inputCount <= 0 Then Return 0
Dim blockSize = InputBlockSize
Dim remaining = inputCount
Dim inPtr = inputOffset
Dim outPtr = outputOffset
While remaining >= blockSize
If encrypt Then
core.EncryptBlock(input, inPtr, output, outPtr)
Else
core.DecryptBlock(input, inPtr, output, outPtr)
End If
inPtr += blockSize
outPtr += blockSize
remaining -= blockSize
End While
Return inputCount - remaining
End Function
Public Function TransformFinalBlock(input() As Byte, inputOffset As Integer, inputCount As Integer) As Byte() Implements ICryptoTransform.TransformFinalBlock
Dim blockSize = InputBlockSize
Dim buffer() As Byte
If paddingMode = PaddingMode.None Then
buffer = New Byte(inputCount - 1) {}
TransformBlock(input, inputOffset, inputCount, buffer, 0)
Return buffer
End If
If encrypt Then
Dim paddedLength As Integer
Select Case paddingMode
Case PaddingMode.Zeros
paddedLength = ((inputCount + blockSize - 1) \ blockSize) * blockSize
Case PaddingMode.PKCS7, PaddingMode.ANSIX923, PaddingMode.ISO10126
Dim padLen = blockSize - (inputCount Mod blockSize)
If padLen = 0 Then padLen = blockSize
paddedLength = inputCount + padLen
Case Else
Throw New NotSupportedException("Unsupported padding mode: " & paddingMode.ToString())
End Select
buffer = New Byte(paddedLength - 1) {}
Array.Copy(input, inputOffset, buffer, 0, inputCount)
Dim padVal As Byte = CByte(paddedLength - inputCount)
Select Case paddingMode
Case PaddingMode.PKCS7
For i = inputCount To paddedLength - 1
buffer(i) = padVal
Next
Case PaddingMode.ANSIX923
For i = inputCount To paddedLength - 2
buffer(i) = 0
Next
buffer(paddedLength - 1) = padVal
Case PaddingMode.ISO10126
For i = inputCount To paddedLength - 2
buffer(i) = CByte(rnd.Next(0, 256))
Next
buffer(paddedLength - 1) = padVal
End Select
For i = 0 To buffer.Length - 1 Step blockSize
core.EncryptBlock(buffer, i, buffer, i)
Next
Return buffer
Else
If (inputCount Mod blockSize) <> 0 Then
Throw New CryptographicException("Encrypted data is not a multiple of block size.")
End If
buffer = New Byte(inputCount - 1) {}
TransformBlock(input, inputOffset, inputCount, buffer, 0)
Dim padVal As Integer = buffer(buffer.Length - 1)
If padVal <= 0 OrElse padVal > blockSize Then
Throw New CryptographicException("Invalid padding.")
End If
Select Case paddingMode
Case PaddingMode.PKCS7
For i = buffer.Length - padVal To buffer.Length - 1
If buffer(i) <> padVal Then
Throw New CryptographicException("Invalid PKCS7 padding value.")
End If
Next
Case PaddingMode.ANSIX923
For i = buffer.Length - padVal To buffer.Length - 2
If buffer(i) <> 0 Then
Throw New CryptographicException("Invalid ANSIX923 padding value.")
End If
Next
Case PaddingMode.ISO10126
' no need to check random bytes, only length byte matters
Case Else
Throw New NotSupportedException("Unsupported padding mode: " & paddingMode.ToString())
End Select
Dim result(buffer.Length - padVal - 1) As Byte
Array.Copy(buffer, 0, result, 0, result.Length)
Return result
End If
End Function
Public Sub Dispose() Implements IDisposable.Dispose
' No resources to dispose
End Sub
End Class

View File

@ -70,6 +70,12 @@ Public Class SeedEcbTransform
Dim blockSize = InputBlockSize
Dim buffer() As Byte
If paddingMode = PaddingMode.None Then
buffer = New Byte(inputCount - 1) {}
TransformBlock(input, inputOffset, inputCount, buffer, 0)
Return buffer
End If
If encrypt Then
Dim paddedLength As Integer
Select Case paddingMode