mirror of
https://github.com/gnh1201/welsonjs.git
synced 2025-10-27 11:01:16 +00:00
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:
parent
ec03bf415d
commit
2a8c4d196c
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
51
WelsonJS.Toolkit/WelsonJS.Cryptography/HightAlgorithm.vb
Normal file
51
WelsonJS.Toolkit/WelsonJS.Cryptography/HightAlgorithm.vb
Normal 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
|
||||
139
WelsonJS.Toolkit/WelsonJS.Cryptography/HightCore.vb
Normal file
139
WelsonJS.Toolkit/WelsonJS.Cryptography/HightCore.vb
Normal 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
|
||||
156
WelsonJS.Toolkit/WelsonJS.Cryptography/HightEcbTransform.vb
Normal file
156
WelsonJS.Toolkit/WelsonJS.Cryptography/HightEcbTransform.vb
Normal 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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user