Add ARIA cryptography algorithm

Add ARIA cryptography algorithm
This commit is contained in:
Namhyeon Go 2025-07-19 19:07:05 +09:00
parent 848a4359fa
commit ec03bf415d
4 changed files with 531 additions and 7 deletions

View File

@ -9,19 +9,32 @@ Imports System.Text
Module Program
Sub Main(args As String())
' SEED algorithm
Console.WriteLine("Start SEED encryption and decryption test")
Dim cipher As New WelsonJS.Cryptography.SeedAlgorithm()
Dim seedCipher As New WelsonJS.Cryptography.SeedAlgorithm()
seedCipher.Key = {&H88, &HE3, &H4F, &H8F, &H8, &H17, &H79, &HF1, &HE9, &HF3, &H94, &H37, &HA, &HD4, &H5, &H89}
' seedCipher.IV = {&H26, &H8D, &H66, &HA7, &H35, &HA8, &H1A, &H81, &H6F, &HBA, &HD9, &HFA, &H36, &H16, &H25, &H1}
seedCipher.Mode = CipherMode.ECB
seedCipher.Padding = PaddingMode.PKCS7
RunTest(seedCipher)
Console.WriteLine()
cipher.Key = {&H88, &HE3, &H4F, &H8F, &H8, &H17, &H79, &HF1, &HE9, &HF3, &H94, &H37, &HA, &HD4, &H5, &H89}
' cipher.IV = {&H26, &H8D, &H66, &HA7, &H35, &HA8, &H1A, &H81, &H6F, &HBA, &HD9, &HFA, &H36, &H16, &H25, &H1}
cipher.Mode = CipherMode.ECB
cipher.Padding = PaddingMode.PKCS7
' ARIA algorithm
Console.WriteLine("Start ARIA encryption and decryption test")
Dim ariaCipher As New WelsonJS.Cryptography.AriaAlgorithm()
ariaCipher.Key = {&H0, &H11, &H22, &H33, &H44, &H55, &H66, &H77, &H88, &H99, &HAA, &HBB, &HCC, &HDD, &HEE, &HFF}
' ariaChiper.IV = {&H0F, &H1E, &H2D, &H3C, &H4B, &H5A, &H69, &H78, &H87, &H96, &HA5, &HB4, &HC3, &HD2, &HE1, &HF0}
ariaCipher.Mode = CipherMode.ECB
ariaCipher.Padding = PaddingMode.PKCS7
RunTest(ariaCipher)
Console.WriteLine()
RunTest(cipher)
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() = {&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}
Console.WriteLine("Key (HEX):")
PrintHex(cipher.Key)

View File

@ -0,0 +1,57 @@
' AriaAlgorithm.cs(WelsonJS.Cryptography)
' SPDX-License-Identifier: MIT
' SPDX-FileCopyrightText: 2025 Namhyeon Go <gnh1201@catswords.re.kr>, Catswords OSS And WelsonJS Contributors
' https://github.com/gnh1201/welsonjs
'
Imports System.Security.Cryptography
Public Class AriaAlgorithm
Inherits SymmetricAlgorithm
Public Sub New()
LegalBlockSizesValue = New KeySizes() {New KeySizes(128, 128, 0)}
LegalKeySizesValue = New KeySizes() {New KeySizes(128, 256, 64)}
Me.BlockSize = 128
Me.KeySize = 128
Me.FeedbackSize = 128
Me.Mode = CipherMode.ECB
Me.Padding = PaddingMode.PKCS7
Me.Key = New Byte(15) {}
Me.IV = New Byte(15) {}
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 AriaEcbTransform(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,293 @@
' AriaCore.vb (WelsonJS.Cryptography)
' SPDX-License-Identifier: MIT
' SPDX-FileCopyrightText: 2025 Namhyeon Go <gnh1201@catswords.re.kr>, Catswords OSS And WelsonJS Contributors
' https://github.com/gnh1201/welsonjs
'
' ARIA Core VB.NET Implementation with S-box, inverse S-box, and T-table generation
Public Class AriaCore
Public Shared ReadOnly S1(255) As Byte
Public Shared ReadOnly X1(255) As Byte
Public Shared ReadOnly S2(255) As Byte
Public Shared ReadOnly X2(255) As Byte
Public Shared ReadOnly TS1(255) As UInteger
Public Shared ReadOnly TS2(255) As UInteger
Public Shared ReadOnly TX1(255) As UInteger
Public Shared ReadOnly TX2(255) As UInteger
Private roundKeys()() As UInteger
Private roundCount As Integer = 12
Public Sub New(key() As Byte)
Select Case key.Length
Case 16
roundCount = 12
Case 24
roundCount = 14
Case 32
roundCount = 16
Case Else
Throw New ArgumentException("Only 128, 192, or 256-bit keys are supported.")
End Select
GenerateRoundKeys(key)
End Sub
Public Sub EncryptBlock(input() As Byte, inOffset As Integer, output() As Byte, outOffset As Integer)
Dim x(3) As UInteger
For i = 0 To 3
x(i) = BitConverter.ToUInt32(input, inOffset + i * 4)
Next
For i = 0 To 3
x(i) = x(i) Xor roundKeys(0)(i)
Next
For r = 1 To roundCount - 1
If r = 3 Or r = 7 Then
x = FL(x, roundKeys(r))
End If
x = FO(x)
For i = 0 To 3
x(i) = x(i) Xor roundKeys(r)(i)
Next
Next
x = FO(x)
For i = 0 To 3
x(i) = x(i) Xor roundKeys(roundCount)(i)
Next
For i = 0 To 3
Dim b() As Byte = BitConverter.GetBytes(x(i))
Array.Copy(b, 0, output, outOffset + i * 4, 4)
Next
End Sub
Public Sub DecryptBlock(input() As Byte, inOffset As Integer, output() As Byte, outOffset As Integer)
Dim x(3) As UInteger
For i = 0 To 3
x(i) = BitConverter.ToUInt32(input, inOffset + i * 4)
Next
For i = 0 To 3
x(i) = x(i) Xor roundKeys(roundCount)(i)
Next
For r = roundCount - 1 To 1 Step -1
x = RFO(x)
If r = 3 Or r = 7 Then
x = FLInv(x, roundKeys(r))
End If
For i = 0 To 3
x(i) = x(i) Xor roundKeys(r)(i)
Next
Next
x = RFO(x)
For i = 0 To 3
x(i) = x(i) Xor roundKeys(0)(i)
Next
For i = 0 To 3
Dim b() As Byte = BitConverter.GetBytes(x(i))
Array.Copy(b, 0, output, outOffset + i * 4, 4)
Next
End Sub
Private Function FO(x() As UInteger) As UInteger()
Dim y(3) As UInteger
For i = 0 To 3
Dim b0 As Byte = (x(i) >> 24) And &HFF
Dim b1 As Byte = (x(i) >> 16) And &HFF
Dim b2 As Byte = (x(i) >> 8) And &HFF
Dim b3 As Byte = x(i) And &HFF
y(i) = (CUInt(S1(b0)) << 24) Or (CUInt(S2(b1)) << 16) Or (CUInt(S1(b2)) << 8) Or S2(b3)
Next
Return M(y)
End Function
Private Function RFO(x() As UInteger) As UInteger()
Dim y(3) As UInteger
y = M(x)
For i = 0 To 3
Dim b0 As Byte = (y(i) >> 24) And &HFF
Dim b1 As Byte = (y(i) >> 16) And &HFF
Dim b2 As Byte = (y(i) >> 8) And &HFF
Dim b3 As Byte = y(i) And &HFF
x(i) = (CUInt(X1(b0)) << 24) Or (CUInt(X2(b1)) << 16) Or (CUInt(X1(b2)) << 8) Or X2(b3)
Next
Return x
End Function
Private Function M(x() As UInteger) As UInteger()
Dim y(3) As UInteger
y(0) = x(0) Xor RotateLeft(x(1), 8) Xor RotateLeft(x(2), 16) Xor RotateLeft(x(3), 24)
y(1) = x(1) Xor RotateLeft(x(2), 8) Xor RotateLeft(x(3), 16) Xor RotateLeft(x(0), 24)
y(2) = x(2) Xor RotateLeft(x(3), 8) Xor RotateLeft(x(0), 16) Xor RotateLeft(x(1), 24)
y(3) = x(3) Xor RotateLeft(x(0), 8) Xor RotateLeft(x(1), 16) Xor RotateLeft(x(2), 24)
Return y
End Function
Private Function RotateLeft(val As UInteger, bits As Integer) As UInteger
Return ((val << bits) Or (val >> (32 - bits))) And &HFFFFFFFFUI
End Function
Private Sub GenerateRoundKeys(key() As Byte)
roundKeys = New UInteger(roundCount)() {}
For r = 0 To roundCount
roundKeys(r) = New UInteger(3) {}
Next
Dim w0(3), w1(3), w2(3), w3(3) As UInteger
Dim tempKey(7) As UInteger
For i = 0 To (key.Length \ 4) - 1
tempKey(i) = BitConverter.ToUInt32(key, i * 4)
Next
For i = 0 To 3
w0(i) = tempKey(i)
Next
Dim c1 As UInteger() = {&H517CC1B7UI, &H27220A94UI, &HFE13ABE8UI, &HFA9A6EE0UI}
Dim c2 As UInteger() = {&H6DB14ACCUI, &H9E21C820UI, &HFF28B1D5UI, &HEE36D2E6UI}
Dim c3 As UInteger() = {&HDB92F2FBUI, &H61A64DF2UI, &HDC04B4DFUI, &H1BF429C3UI}
w1 = FO(XorBlock(w0, c1))
w2 = FO(XorBlock(w1, c2))
w3 = FO(XorBlock(w2, c3))
Dim rk(,) As UInteger = {
{0, 19}, {1, 31}, {2, 19}, {3, 31},
{0, 19}, {1, 31}, {2, 19}, {3, 31},
{0, 19}, {1, 31}, {2, 19}, {3, 31},
{0, 19}, {1, 31}, {2, 19}, {3, 31}
}
For r = 0 To roundCount
For i = 0 To 3
Select Case r
Case < 4 : roundKeys(r)(i) = RotateLeft(w1(i), rk(r, 1))
Case < 8 : roundKeys(r)(i) = RotateLeft(w2(i), rk(r, 1))
Case < 12 : roundKeys(r)(i) = RotateLeft(w3(i), rk(r, 1))
Case < 16 : roundKeys(r)(i) = RotateLeft(w0(i), rk(r, 1))
End Select
Next
Next
End Sub
' ----- Tables -----
Shared Sub New()
Dim exp(255) As Integer
Dim log(255) As Integer
exp(0) = 1
For i = 1 To 255
Dim j As Integer = (exp(i - 1) << 1) Xor exp(i - 1)
If (j And &H100) <> 0 Then j = j Xor &H11B
exp(i) = j
Next
For i = 1 To 254
log(exp(i)) = i
Next
Dim A(7, 7) As Integer
Dim AInit(,) As Integer = {
{1, 0, 0, 0, 1, 1, 1, 1},
{1, 1, 0, 0, 0, 1, 1, 1},
{1, 1, 1, 0, 0, 0, 1, 1},
{1, 1, 1, 1, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 0, 0, 0},
{0, 1, 1, 1, 1, 1, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 0},
{0, 0, 0, 1, 1, 1, 1, 1}
}
For i = 0 To 7 : For j = 0 To 7 : A(i, j) = AInit(i, j) : Next : Next
Dim B(7, 7) As Integer
Dim BInit(,) As Integer = {
{0, 1, 0, 1, 1, 1, 1, 0},
{0, 0, 1, 1, 1, 1, 0, 1},
{1, 1, 0, 1, 0, 1, 1, 1},
{1, 0, 0, 1, 1, 1, 0, 1},
{0, 0, 1, 0, 1, 1, 0, 0},
{1, 0, 0, 0, 0, 0, 0, 1},
{0, 1, 0, 1, 1, 1, 0, 1},
{1, 1, 0, 1, 0, 0, 1, 1}
}
For i = 0 To 7 : For j = 0 To 7 : B(i, j) = BInit(i, j) : Next : Next
For i = 0 To 255
Dim t As Integer = 0, p As Integer
If i = 0 Then
p = 0
Else
p = exp(255 - log(i))
End If
For j = 0 To 7
Dim s As Integer = 0
For k = 0 To 7
If ((p >> (7 - k)) And 1) <> 0 Then
s = s Xor A(k, j)
End If
Next
t = (t << 1) Xor s
Next
t = t Xor &H63
S1(i) = CByte(t)
X1(t) = CByte(i)
Next
For i = 0 To 255
Dim t As Integer = 0, p As Integer
If i = 0 Then
p = 0
Else
p = exp((247 * log(i)) Mod 255)
End If
For j = 0 To 7
Dim s As Integer = 0
For k = 0 To 7
If ((p >> k) And 1) <> 0 Then
s = s Xor B(7 - j, k)
End If
Next
t = (t << 1) Xor s
Next
t = t Xor &HE2
S2(i) = CByte(t)
X2(t) = CByte(i)
Next
For i = 0 To 255
TS1(i) = CUInt(&H10101 * (S1(i) And &HFF))
TS2(i) = CUInt(&H1000101 * (S2(i) And &HFF))
TX1(i) = CUInt(&H1010001 * (X1(i) And &HFF))
TX2(i) = CUInt(&H1010100 * (X2(i) And &HFF))
Next
End Sub
Private Function XorBlock(a() As UInteger, b() As UInteger) As UInteger()
Dim r(3) As UInteger
For i = 0 To 3
r(i) = a(i) Xor b(i)
Next
Return r
End Function
Private Function FL(x() As UInteger, k() As UInteger) As UInteger()
Dim y(3) As UInteger
y(0) = x(0) Xor RotateLeft((x(1) And k(0)), 1)
y(1) = x(1) Xor (y(0) Or k(1))
y(2) = x(2) Xor RotateLeft((x(3) Or k(2)), 1)
y(3) = x(3) Xor (y(2) And k(3))
Return y
End Function
Private Function FLInv(x() As UInteger, k() As UInteger) As UInteger()
Dim y(3) As UInteger
y(3) = x(3) Xor ((x(2) Or k(2)) And &HFFFFFFFFUI)
y(2) = x(2) Xor RotateLeft((y(3) Or k(2)), 1)
y(1) = x(1) Xor ((x(0) And k(0)) And &HFFFFFFFFUI)
y(0) = x(0) Xor RotateLeft((y(1) And k(0)), 1)
Return y
End Function
End Class

View File

@ -0,0 +1,161 @@
' AriaEcbTransform.cs (WelsonJS.Cryptography)
' SPDX-License-Identifier: MIT
' SPDX-FileCopyrightText: 2025 Namhyeon Go <gnh1201@catswords.re.kr>, Catswords OSS And WelsonJS Contributors
' https://github.com/gnh1201/welsonjs
Imports System.Security.Cryptography
Public Class AriaEcbTransform
Implements ICryptoTransform
Private ReadOnly rnd As New Random()
Private ReadOnly seedCore As SeedCore
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)
seedCore = New SeedCore(key)
encrypt = encryptMode
paddingMode = mode
End Sub
Public ReadOnly Property InputBlockSize As Integer Implements ICryptoTransform.InputBlockSize
Get
Return 16
End Get
End Property
Public ReadOnly Property OutputBlockSize As Integer Implements ICryptoTransform.OutputBlockSize
Get
Return 16
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
seedCore.EncryptBlock(input, inPtr, output, outPtr)
Else
seedCore.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 encrypt Then
Dim paddedLength As Integer
Select Case paddingMode
Case PaddingMode.None
If (inputCount Mod blockSize) <> 0 Then
Throw New CryptographicException("Input data is not a multiple of block size and PaddingMode is None.")
End If
paddedLength = inputCount
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
seedCore.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