Fix SEED cryptography algorithm

Fix SEED cryptography algorithm
This commit is contained in:
Namhyeon Go 2025-07-09 11:20:54 +09:00
parent cb649c88ed
commit 848a4359fa
3 changed files with 101 additions and 141 deletions

View File

@ -23,6 +23,9 @@ 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}
Console.WriteLine("Key (HEX):")
PrintHex(cipher.Key)
Console.WriteLine("Original bytes (HEX):")
PrintHex(inputBytes)

View File

@ -156,11 +156,21 @@ Public Class SeedCore
KeySchedule(key)
End Sub
' Extract a byte (0 = LSB, 3 = MSB)
Private Shared Function GetByte(n As UInteger, index As Integer) As Byte
Return CByte((n >> (index * 8)) And &HFF)
End Function
Private Shared Function ToUInt32BE(data() As Byte, offset As Integer) As UInteger
Return (CUInt(data(offset)) << 24) Or (CUInt(data(offset + 1)) << 16) Or (CUInt(data(offset + 2)) << 8) Or CUInt(data(offset + 3))
End Function
Private Shared Sub WriteUInt32BE(value As UInteger, output() As Byte, offset As Integer)
output(offset) = CByte((value >> 24) And &HFF)
output(offset + 1) = CByte((value >> 16) And &HFF)
output(offset + 2) = CByte((value >> 8) And &HFF)
output(offset + 3) = CByte(value And &HFF)
End Sub
Private Shared Function RoundFunction(T0 As UInteger, T1 As UInteger) As Tuple(Of UInteger, UInteger)
T1 = T1 Xor T0
T1 = SS0(GetByte(T1, 0)) Xor SS1(GetByte(T1, 1)) Xor SS2(GetByte(T1, 2)) Xor SS3(GetByte(T1, 3))
@ -173,10 +183,10 @@ Public Class SeedCore
End Function
Private Sub KeySchedule(userKey As Byte())
Dim A As UInteger = BitConverter.ToUInt32(userKey, 0)
Dim B As UInteger = BitConverter.ToUInt32(userKey, 4)
Dim C As UInteger = BitConverter.ToUInt32(userKey, 8)
Dim D As UInteger = BitConverter.ToUInt32(userKey, 12)
Dim A As UInteger = ToUInt32BE(userKey, 0)
Dim B As UInteger = ToUInt32BE(userKey, 4)
Dim C As UInteger = ToUInt32BE(userKey, 8)
Dim D As UInteger = ToUInt32BE(userKey, 12)
For i As Integer = 0 To 15
Dim T0 As UInteger = (A + C - KC(i)) And &HFFFFFFFFUI
@ -185,66 +195,62 @@ Public Class SeedCore
roundKey(2 * i + 1) = SS0(GetByte(T1, 0)) Xor SS1(GetByte(T1, 1)) Xor SS2(GetByte(T1, 2)) Xor SS3(GetByte(T1, 3))
If i Mod 2 = 0 Then
Dim tmpA = A
A = (A >> 8) Or (B << 24)
B = (B >> 8) Or (tmpA << 24)
Dim AB As ULong = (CLng(A) << 32) Or B
AB = ((AB >> 8) Or (AB << 56)) And &HFFFFFFFFFFFFFFFFUL
A = CUInt(AB >> 32)
B = CUInt(AB And &HFFFFFFFFUL)
Else
Dim tmpC = C
C = (C << 8) Or (D >> 24)
D = (D << 8) Or (tmpC >> 24)
Dim CD As ULong = (CLng(C) << 32) Or D
CD = ((CD << 8) Or (CD >> 56)) And &HFFFFFFFFFFFFFFFFUL
C = CUInt(CD >> 32)
D = CUInt(CD And &HFFFFFFFFUL)
End If
Next
End Sub
Public Sub EncryptBlock(input() As Byte, inOffset As Integer, output() As Byte, outOffset As Integer)
Dim L0 = BitConverter.ToUInt32(input, inOffset)
Dim L1 = BitConverter.ToUInt32(input, inOffset + 4)
Dim R0 = BitConverter.ToUInt32(input, inOffset + 8)
Dim R1 = BitConverter.ToUInt32(input, inOffset + 12)
Dim L0 = ToUInt32BE(input, inOffset)
Dim L1 = ToUInt32BE(input, inOffset + 4)
Dim R0 = ToUInt32BE(input, inOffset + 8)
Dim R1 = ToUInt32BE(input, inOffset + 12)
For i As Integer = 0 To 15
Dim t = RoundFunction(R0 Xor roundKey(2 * i), R1 Xor roundKey(2 * i + 1))
Dim T0 = t.Item1
Dim T1 = t.Item2
L0 = L0 Xor T0
L1 = L1 Xor T1
' swap
Dim tmp0 = L0 : Dim tmp1 = L1
Dim temp0 = L0 Xor T0
Dim temp1 = L1 Xor T1
L0 = R0 : L1 = R1
R0 = tmp0 : R1 = tmp1
R0 = temp0 : R1 = temp1
Next
Array.Copy(BitConverter.GetBytes(R0), 0, output, outOffset, 4)
Array.Copy(BitConverter.GetBytes(R1), 0, output, outOffset + 4, 4)
Array.Copy(BitConverter.GetBytes(L0), 0, output, outOffset + 8, 4)
Array.Copy(BitConverter.GetBytes(L1), 0, output, outOffset + 12, 4)
WriteUInt32BE(R0, output, outOffset)
WriteUInt32BE(R1, output, outOffset + 4)
WriteUInt32BE(L0, output, outOffset + 8)
WriteUInt32BE(L1, output, outOffset + 12)
End Sub
Public Sub DecryptBlock(input() As Byte, inOffset As Integer, output() As Byte, outOffset As Integer)
Dim L0 = BitConverter.ToUInt32(input, inOffset)
Dim L1 = BitConverter.ToUInt32(input, inOffset + 4)
Dim R0 = BitConverter.ToUInt32(input, inOffset + 8)
Dim R1 = BitConverter.ToUInt32(input, inOffset + 12)
Dim L0 = ToUInt32BE(input, inOffset)
Dim L1 = ToUInt32BE(input, inOffset + 4)
Dim R0 = ToUInt32BE(input, inOffset + 8)
Dim R1 = ToUInt32BE(input, inOffset + 12)
For i As Integer = 0 To 15
Dim t = RoundFunction(R0 Xor roundKey(30 - 2 * i), R1 Xor roundKey(31 - 2 * i))
Dim T0 = t.Item1
Dim T1 = t.Item2
L0 = L0 Xor T0
L1 = L1 Xor T1
' swap
Dim tmp0 = L0 : Dim tmp1 = L1
Dim temp0 = L0 Xor T0
Dim temp1 = L1 Xor T1
L0 = R0 : L1 = R1
R0 = tmp0 : R1 = tmp1
R0 = temp0 : R1 = temp1
Next
Array.Copy(BitConverter.GetBytes(R0), 0, output, outOffset, 4)
Array.Copy(BitConverter.GetBytes(R1), 0, output, outOffset + 4, 4)
Array.Copy(BitConverter.GetBytes(L0), 0, output, outOffset + 8, 4)
Array.Copy(BitConverter.GetBytes(L1), 0, output, outOffset + 12, 4)
WriteUInt32BE(R0, output, outOffset)
WriteUInt32BE(R1, output, outOffset + 4)
WriteUInt32BE(L0, output, outOffset + 8)
WriteUInt32BE(L1, output, outOffset + 12)
End Sub
End Class

View File

@ -2,7 +2,7 @@
' 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 SeedEcbTransform
@ -45,55 +45,47 @@ Public Class SeedEcbTransform
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
End If
If inputCount <= 0 Then Return 0
Dim blockSize = InputBlockSize
Dim remaining = inputCount
Dim inPtr = inputOffset
Dim outPtr = outputOffset
For i As Integer = 0 To inputCount - 1 Step blockSize
While remaining >= blockSize
If encrypt Then
seedCore.EncryptBlock(input, inputOffset + i, output, outputOffset + i)
seedCore.EncryptBlock(input, inPtr, output, outPtr)
Else
seedCore.DecryptBlock(input, inputOffset + i, output, outputOffset + i)
seedCore.DecryptBlock(input, inPtr, output, outPtr)
End If
Next
inPtr += blockSize
outPtr += blockSize
remaining -= blockSize
End While
Return inputCount
Return inputCount - remaining
End Function
Public Function TransformFinalBlock(input() As Byte, inputOffset As Integer, inputCount As Integer) As Byte() Implements ICryptoTransform.TransformFinalBlock
If inputCount = 0 Then
Return Array.Empty(Of Byte)()
End If
Dim blockSize As Integer = InputBlockSize
Dim paddedLength As Integer
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
' None 패딩은 추가 블록 없음
paddedLength = inputCount
Case PaddingMode.Zeros
' Zeros 패딩은 추가 블록 필요 없음
paddedLength = ((inputCount + blockSize - 1) \ blockSize) * blockSize
Case PaddingMode.PKCS7, PaddingMode.ANSIX923, PaddingMode.ISO10126
' PKCS7. ANSIX923, ISO10126 패딩은 입력이 블록 배수면 +1 블록 추가
' (설명) 블록암호에서 블록 길이와 같은 길이의 원문을 넣으면, 암호화문 길이가 원문 길이의 2배가 되는 원인은 여기에 기인한다.
Dim fullBlocks As Integer = inputCount \ blockSize
Dim remainder As Integer = inputCount Mod blockSize
If remainder = 0 Then
paddedLength = (fullBlocks + 1) * blockSize ' 추가 블록 붙임
Else
paddedLength = (fullBlocks + 1) * blockSize
End If
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())
@ -102,32 +94,30 @@ Public Class SeedEcbTransform
buffer = New Byte(paddedLength - 1) {}
Array.Copy(input, inputOffset, buffer, 0, inputCount)
If paddingMode = PaddingMode.PKCS7 Then
Dim padValue As Byte = CByte(paddedLength - inputCount)
For i As Integer = inputCount To paddedLength - 1
buffer(i) = padValue
Next
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
ElseIf paddingMode = PaddingMode.ANSIX923 Then
Dim padValue As Byte = CByte(paddedLength - inputCount)
For i As Integer = inputCount To paddedLength - 2
buffer(i) = 0
Next
buffer(paddedLength - 1) = padValue
ElseIf paddingMode = PaddingMode.ISO10126 Then
Dim padValue As Byte = CByte(paddedLength - inputCount)
For i As Integer = inputCount To paddedLength - 2
buffer(i) = CByte(rnd.Next(0, 256))
Next
buffer(paddedLength - 1) = padValue
End If
TransformBlock(buffer, 0, paddedLength, buffer, 0)
For i = 0 To buffer.Length - 1 Step blockSize
seedCore.EncryptBlock(buffer, i, buffer, i)
Next
Return buffer
Else
' Decryption
If (inputCount Mod blockSize) <> 0 Then
Throw New CryptographicException("Encrypted data is not a multiple of block size.")
End If
@ -135,76 +125,37 @@ Public Class SeedEcbTransform
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.None
Return buffer
Case PaddingMode.Zeros
Dim trimLength As Integer = buffer.Length
While trimLength > 0 AndAlso buffer(trimLength - 1) = 0
trimLength -= 1
End While
Dim result(trimLength - 1) As Byte
Array.Copy(buffer, 0, result, 0, trimLength)
Return result
Case PaddingMode.PKCS7
Dim padValue As Integer = buffer(buffer.Length - 1)
If padValue <= 0 OrElse padValue > blockSize Then
Throw New CryptographicException("Invalid PKCS7 padding.")
End If
For i As Integer = buffer.Length - padValue To buffer.Length - 1
If buffer(i) <> padValue Then
For i = buffer.Length - padVal To buffer.Length - 1
If buffer(i) <> padVal Then
Throw New CryptographicException("Invalid PKCS7 padding value.")
End If
Next
Dim unpaddedLength As Integer = buffer.Length - padValue
If unpaddedLength < 0 Then
Throw New CryptographicException("Invalid unpadded length.")
End If
Dim result(unpaddedLength - 1) As Byte
Array.Copy(buffer, 0, result, 0, unpaddedLength)
Return result
Case PaddingMode.ANSIX923
Dim padValue As Integer = buffer(buffer.Length - 1)
If padValue <= 0 OrElse padValue > blockSize Then
Throw New CryptographicException("Invalid ANSIX923 padding.")
End If
For i As Integer = buffer.Length - padValue To buffer.Length - 2
For i = buffer.Length - padVal To buffer.Length - 2
If buffer(i) <> 0 Then
Throw New CryptographicException("Invalid ANSIX923 padding value.")
End If
Next
Dim unpaddedLengthAnsix As Integer = buffer.Length - padValue
If unpaddedLengthAnsix < 0 Then
Throw New CryptographicException("Invalid unpadded length.")
End If
Dim resultAnsix(unpaddedLengthAnsix - 1) As Byte
Array.Copy(buffer, 0, resultAnsix, 0, unpaddedLengthAnsix)
Return resultAnsix
Case PaddingMode.ISO10126
Dim padValue As Integer = buffer(buffer.Length - 1)
If padValue <= 0 OrElse padValue > blockSize Then
Throw New CryptographicException("Invalid ISO10126 padding.")
End If
' Check the last byte (length)
Dim unpaddedLengthIso As Integer = buffer.Length - padValue
If unpaddedLengthIso < 0 Then
Throw New CryptographicException("Invalid unpadded length.")
End If
Dim resultIso(unpaddedLengthIso - 1) As Byte
Array.Copy(buffer, 0, resultIso, 0, unpaddedLengthIso)
Return resultIso
' 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
' Nothing
' No resources to dispose
End Sub
End Class
End Class