mirror of
https://github.com/gnh1201/welsonjs.git
synced 2025-10-27 02:51:17 +00:00
Fix SEED cryptography algorithm
Fix SEED cryptography algorithm
This commit is contained in:
parent
cb649c88ed
commit
848a4359fa
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user