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) 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}
Console.WriteLine("Key (HEX):")
PrintHex(cipher.Key)
Console.WriteLine("Original bytes (HEX):") Console.WriteLine("Original bytes (HEX):")
PrintHex(inputBytes) PrintHex(inputBytes)

View File

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

View File

@ -2,7 +2,7 @@
' SPDX-License-Identifier: MIT ' SPDX-License-Identifier: MIT
' SPDX-FileCopyrightText: 2025 Namhyeon Go <gnh1201@catswords.re.kr>, Catswords OSS And WelsonJS Contributors ' SPDX-FileCopyrightText: 2025 Namhyeon Go <gnh1201@catswords.re.kr>, Catswords OSS And WelsonJS Contributors
' https://github.com/gnh1201/welsonjs ' https://github.com/gnh1201/welsonjs
'
Imports System.Security.Cryptography Imports System.Security.Cryptography
Public Class SeedEcbTransform Public Class SeedEcbTransform
@ -45,55 +45,47 @@ Public Class SeedEcbTransform
Public Function TransformBlock(input() As Byte, inputOffset As Integer, inputCount As Integer, Public Function TransformBlock(input() As Byte, inputOffset As Integer, inputCount As Integer,
output() As Byte, outputOffset As Integer) As Integer Implements ICryptoTransform.TransformBlock output() As Byte, outputOffset As Integer) As Integer Implements ICryptoTransform.TransformBlock
If inputCount <= 0 Then If inputCount <= 0 Then Return 0
Return 0
End If
Dim blockSize = InputBlockSize 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 If encrypt Then
seedCore.EncryptBlock(input, inputOffset + i, output, outputOffset + i) seedCore.EncryptBlock(input, inPtr, output, outPtr)
Else Else
seedCore.DecryptBlock(input, inputOffset + i, output, outputOffset + i) seedCore.DecryptBlock(input, inPtr, output, outPtr)
End If End If
Next inPtr += blockSize
outPtr += blockSize
remaining -= blockSize
End While
Return inputCount Return inputCount - remaining
End Function End Function
Public Function TransformFinalBlock(input() As Byte, inputOffset As Integer, inputCount As Integer) As Byte() Implements ICryptoTransform.TransformFinalBlock Public Function TransformFinalBlock(input() As Byte, inputOffset As Integer, inputCount As Integer) As Byte() Implements ICryptoTransform.TransformFinalBlock
If inputCount = 0 Then Dim blockSize = InputBlockSize
Return Array.Empty(Of Byte)()
End If
Dim blockSize As Integer = InputBlockSize
Dim paddedLength As Integer
Dim buffer() As Byte Dim buffer() As Byte
If encrypt Then If encrypt Then
Dim paddedLength As Integer
Select Case paddingMode Select Case paddingMode
Case PaddingMode.None Case PaddingMode.None
If (inputCount Mod blockSize) <> 0 Then If (inputCount Mod blockSize) <> 0 Then
Throw New CryptographicException("Input data is not a multiple of block size and PaddingMode is None.") Throw New CryptographicException("Input data is not a multiple of block size and PaddingMode is None.")
End If End If
' None 패딩은 추가 블록 없음
paddedLength = inputCount paddedLength = inputCount
Case PaddingMode.Zeros Case PaddingMode.Zeros
' Zeros 패딩은 추가 블록 필요 없음
paddedLength = ((inputCount + blockSize - 1) \ blockSize) * blockSize paddedLength = ((inputCount + blockSize - 1) \ blockSize) * blockSize
Case PaddingMode.PKCS7, PaddingMode.ANSIX923, PaddingMode.ISO10126 Case PaddingMode.PKCS7, PaddingMode.ANSIX923, PaddingMode.ISO10126
' PKCS7. ANSIX923, ISO10126 패딩은 입력이 블록 배수면 +1 블록 추가 Dim padLen = blockSize - (inputCount Mod blockSize)
' (설명) 블록암호에서 블록 길이와 같은 길이의 원문을 넣으면, 암호화문 길이가 원문 길이의 2배가 되는 원인은 여기에 기인한다. If padLen = 0 Then padLen = blockSize
Dim fullBlocks As Integer = inputCount \ blockSize paddedLength = inputCount + padLen
Dim remainder As Integer = inputCount Mod blockSize
If remainder = 0 Then
paddedLength = (fullBlocks + 1) * blockSize ' 추가 블록 붙임
Else
paddedLength = (fullBlocks + 1) * blockSize
End If
Case Else Case Else
Throw New NotSupportedException("Unsupported padding mode: " & paddingMode.ToString()) Throw New NotSupportedException("Unsupported padding mode: " & paddingMode.ToString())
@ -102,32 +94,30 @@ Public Class SeedEcbTransform
buffer = New Byte(paddedLength - 1) {} buffer = New Byte(paddedLength - 1) {}
Array.Copy(input, inputOffset, buffer, 0, inputCount) Array.Copy(input, inputOffset, buffer, 0, inputCount)
If paddingMode = PaddingMode.PKCS7 Then Dim padVal As Byte = CByte(paddedLength - inputCount)
Dim padValue As Byte = CByte(paddedLength - inputCount) Select Case paddingMode
For i As Integer = inputCount To paddedLength - 1 Case PaddingMode.PKCS7
buffer(i) = padValue For i = inputCount To paddedLength - 1
buffer(i) = padVal
Next Next
Case PaddingMode.ANSIX923
ElseIf paddingMode = PaddingMode.ANSIX923 Then For i = inputCount To paddedLength - 2
Dim padValue As Byte = CByte(paddedLength - inputCount)
For i As Integer = inputCount To paddedLength - 2
buffer(i) = 0 buffer(i) = 0
Next Next
buffer(paddedLength - 1) = padValue buffer(paddedLength - 1) = padVal
Case PaddingMode.ISO10126
ElseIf paddingMode = PaddingMode.ISO10126 Then For i = inputCount To paddedLength - 2
Dim padValue As Byte = CByte(paddedLength - inputCount)
For i As Integer = inputCount To paddedLength - 2
buffer(i) = CByte(rnd.Next(0, 256)) buffer(i) = CByte(rnd.Next(0, 256))
Next Next
buffer(paddedLength - 1) = padValue buffer(paddedLength - 1) = padVal
End If End Select
TransformBlock(buffer, 0, paddedLength, buffer, 0) For i = 0 To buffer.Length - 1 Step blockSize
seedCore.EncryptBlock(buffer, i, buffer, i)
Next
Return buffer Return buffer
Else Else
' Decryption
If (inputCount Mod blockSize) <> 0 Then If (inputCount Mod blockSize) <> 0 Then
Throw New CryptographicException("Encrypted data is not a multiple of block size.") Throw New CryptographicException("Encrypted data is not a multiple of block size.")
End If End If
@ -135,76 +125,37 @@ Public Class SeedEcbTransform
buffer = New Byte(inputCount - 1) {} buffer = New Byte(inputCount - 1) {}
TransformBlock(input, inputOffset, inputCount, buffer, 0) TransformBlock(input, inputOffset, inputCount, buffer, 0)
Select Case paddingMode Dim padVal As Integer = buffer(buffer.Length - 1)
Case PaddingMode.None If padVal <= 0 OrElse padVal > blockSize Then
Return buffer Throw New CryptographicException("Invalid padding.")
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 End If
For i As Integer = buffer.Length - padValue To buffer.Length - 1
If buffer(i) <> padValue Then 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.") Throw New CryptographicException("Invalid PKCS7 padding value.")
End If End If
Next 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 Case PaddingMode.ANSIX923
Dim padValue As Integer = buffer(buffer.Length - 1) For i = buffer.Length - padVal To buffer.Length - 2
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
If buffer(i) <> 0 Then If buffer(i) <> 0 Then
Throw New CryptographicException("Invalid ANSIX923 padding value.") Throw New CryptographicException("Invalid ANSIX923 padding value.")
End If End If
Next 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 Case PaddingMode.ISO10126
Dim padValue As Integer = buffer(buffer.Length - 1) ' no need to check random bytes, only length byte matters
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
Case Else Case Else
Throw New NotSupportedException("Unsupported padding mode: " & paddingMode.ToString()) Throw New NotSupportedException("Unsupported padding mode: " & paddingMode.ToString())
End Select End Select
Dim result(buffer.Length - padVal - 1) As Byte
Array.Copy(buffer, 0, result, 0, result.Length)
Return result
End If End If
End Function End Function
Public Sub Dispose() Implements IDisposable.Dispose Public Sub Dispose() Implements IDisposable.Dispose
' Nothing ' No resources to dispose
End Sub End Sub
End Class End Class