welsonjs/WelsonJS.Toolkit/WelsonJS.Cryptography/SeedEcbTransform.vb
Namhyeon, Go 848a4359fa Fix SEED cryptography algorithm
Fix SEED cryptography algorithm
2025-07-09 11:20:54 +09:00

162 lines
6.1 KiB
VB.net

' SeedEcbTransform.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 SeedEcbTransform
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