Files
SuperVPN/output/Libraries/BouncyCastle.Crypto/Org/BouncyCastle/Crypto/Signers/Iso9796d2Signer.cs
2025-10-09 09:57:24 +09:00

434 lines
9.2 KiB
C#

using System;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Signers;
public class Iso9796d2Signer : ISignerWithRecovery, ISigner
{
[Obsolete("Use 'IsoTrailers' instead")]
public const int TrailerImplicit = 188;
[Obsolete("Use 'IsoTrailers' instead")]
public const int TrailerRipeMD160 = 12748;
[Obsolete("Use 'IsoTrailers' instead")]
public const int TrailerRipeMD128 = 13004;
[Obsolete("Use 'IsoTrailers' instead")]
public const int TrailerSha1 = 13260;
[Obsolete("Use 'IsoTrailers' instead")]
public const int TrailerSha256 = 13516;
[Obsolete("Use 'IsoTrailers' instead")]
public const int TrailerSha512 = 13772;
[Obsolete("Use 'IsoTrailers' instead")]
public const int TrailerSha384 = 14028;
[Obsolete("Use 'IsoTrailers' instead")]
public const int TrailerWhirlpool = 14284;
private IDigest digest;
private IAsymmetricBlockCipher cipher;
private int trailer;
private int keyBits;
private byte[] block;
private byte[] mBuf;
private int messageLength;
private bool fullMessage;
private byte[] recoveredMessage;
private byte[] preSig;
private byte[] preBlock;
public virtual string AlgorithmName => digest.AlgorithmName + "withISO9796-2S1";
public byte[] GetRecoveredMessage()
{
return recoveredMessage;
}
public Iso9796d2Signer(IAsymmetricBlockCipher cipher, IDigest digest, bool isImplicit)
{
this.cipher = cipher;
this.digest = digest;
if (isImplicit)
{
trailer = 188;
return;
}
if (IsoTrailers.NoTrailerAvailable(digest))
{
throw new ArgumentException("no valid trailer", "digest");
}
trailer = IsoTrailers.GetTrailer(digest);
}
public Iso9796d2Signer(IAsymmetricBlockCipher cipher, IDigest digest)
: this(cipher, digest, isImplicit: false)
{
}
public virtual void Init(bool forSigning, ICipherParameters parameters)
{
RsaKeyParameters rsaKeyParameters = (RsaKeyParameters)parameters;
cipher.Init(forSigning, rsaKeyParameters);
keyBits = rsaKeyParameters.Modulus.BitLength;
block = new byte[(keyBits + 7) / 8];
if (trailer == 188)
{
mBuf = new byte[block.Length - digest.GetDigestSize() - 2];
}
else
{
mBuf = new byte[block.Length - digest.GetDigestSize() - 3];
}
Reset();
}
private bool IsSameAs(byte[] a, byte[] b)
{
int num;
if (messageLength > mBuf.Length)
{
if (mBuf.Length > b.Length)
{
return false;
}
num = mBuf.Length;
}
else
{
if (messageLength != b.Length)
{
return false;
}
num = b.Length;
}
bool result = true;
for (int i = 0; i != num; i++)
{
if (a[i] != b[i])
{
result = false;
}
}
return result;
}
private void ClearBlock(byte[] block)
{
Array.Clear(block, 0, block.Length);
}
public virtual void UpdateWithRecoveredMessage(byte[] signature)
{
byte[] array = cipher.ProcessBlock(signature, 0, signature.Length);
if (((array[0] & 0xC0) ^ 0x40) != 0)
{
throw new InvalidCipherTextException("malformed signature");
}
if (((array[^1] & 0xF) ^ 0xC) != 0)
{
throw new InvalidCipherTextException("malformed signature");
}
int num = 0;
if (((array[^1] & 0xFF) ^ 0xBC) == 0)
{
num = 1;
}
else
{
int num2 = ((array[^2] & 0xFF) << 8) | (array[^1] & 0xFF);
if (IsoTrailers.NoTrailerAvailable(digest))
{
throw new ArgumentException("unrecognised hash in signature");
}
if (num2 != IsoTrailers.GetTrailer(digest))
{
throw new InvalidOperationException("signer initialised with wrong digest for trailer " + num2);
}
num = 2;
}
int num3 = 0;
for (num3 = 0; num3 != array.Length && ((array[num3] & 0xF) ^ 0xA) != 0; num3++)
{
}
num3++;
int num4 = array.Length - num - digest.GetDigestSize();
if (num4 - num3 <= 0)
{
throw new InvalidCipherTextException("malformed block");
}
if ((array[0] & 0x20) == 0)
{
fullMessage = true;
recoveredMessage = new byte[num4 - num3];
Array.Copy(array, num3, recoveredMessage, 0, recoveredMessage.Length);
}
else
{
fullMessage = false;
recoveredMessage = new byte[num4 - num3];
Array.Copy(array, num3, recoveredMessage, 0, recoveredMessage.Length);
}
preSig = signature;
preBlock = array;
digest.BlockUpdate(recoveredMessage, 0, recoveredMessage.Length);
messageLength = recoveredMessage.Length;
recoveredMessage.CopyTo(mBuf, 0);
}
public virtual void Update(byte input)
{
digest.Update(input);
if (messageLength < mBuf.Length)
{
mBuf[messageLength] = input;
}
messageLength++;
}
public virtual void BlockUpdate(byte[] input, int inOff, int length)
{
while (length > 0 && messageLength < mBuf.Length)
{
Update(input[inOff]);
inOff++;
length--;
}
digest.BlockUpdate(input, inOff, length);
messageLength += length;
}
public virtual void Reset()
{
digest.Reset();
messageLength = 0;
ClearBlock(mBuf);
if (recoveredMessage != null)
{
ClearBlock(recoveredMessage);
}
recoveredMessage = null;
fullMessage = false;
if (preSig != null)
{
preSig = null;
ClearBlock(preBlock);
preBlock = null;
}
}
public virtual byte[] GenerateSignature()
{
int digestSize = digest.GetDigestSize();
int num = 0;
int num2 = 0;
if (trailer == 188)
{
num = 8;
num2 = block.Length - digestSize - 1;
digest.DoFinal(block, num2);
block[block.Length - 1] = 188;
}
else
{
num = 16;
num2 = block.Length - digestSize - 2;
digest.DoFinal(block, num2);
block[block.Length - 2] = (byte)((uint)trailer >> 8);
block[block.Length - 1] = (byte)trailer;
}
byte b = 0;
int num3 = (digestSize + messageLength) * 8 + num + 4 - keyBits;
if (num3 > 0)
{
int num4 = messageLength - (num3 + 7) / 8;
b = 96;
num2 -= num4;
Array.Copy(mBuf, 0, block, num2, num4);
}
else
{
b = 64;
num2 -= messageLength;
Array.Copy(mBuf, 0, block, num2, messageLength);
}
if (num2 - 1 > 0)
{
for (int num5 = num2 - 1; num5 != 0; num5--)
{
block[num5] = 187;
}
byte[] array2;
byte[] array = (array2 = block);
int num6 = num2 - 1;
nint num7 = num6;
array[num6] = (byte)(array2[num7] ^ 1);
block[0] = 11;
(array2 = block)[0] = (byte)(array2[0] | b);
}
else
{
block[0] = 10;
byte[] array2;
(array2 = block)[0] = (byte)(array2[0] | b);
}
byte[] result = cipher.ProcessBlock(block, 0, block.Length);
messageLength = 0;
ClearBlock(mBuf);
ClearBlock(block);
return result;
}
public virtual bool VerifySignature(byte[] signature)
{
byte[] array;
if (preSig == null)
{
try
{
array = cipher.ProcessBlock(signature, 0, signature.Length);
}
catch (Exception)
{
return false;
}
}
else
{
if (!Arrays.AreEqual(preSig, signature))
{
throw new InvalidOperationException("updateWithRecoveredMessage called on different signature");
}
array = preBlock;
preSig = null;
preBlock = null;
}
if (((array[0] & 0xC0) ^ 0x40) != 0)
{
return ReturnFalse(array);
}
if (((array[^1] & 0xF) ^ 0xC) != 0)
{
return ReturnFalse(array);
}
int num = 0;
if (((array[^1] & 0xFF) ^ 0xBC) == 0)
{
num = 1;
}
else
{
int num2 = ((array[^2] & 0xFF) << 8) | (array[^1] & 0xFF);
if (IsoTrailers.NoTrailerAvailable(digest))
{
throw new ArgumentException("unrecognised hash in signature");
}
if (num2 != IsoTrailers.GetTrailer(digest))
{
throw new InvalidOperationException("signer initialised with wrong digest for trailer " + num2);
}
num = 2;
}
int i;
for (i = 0; i != array.Length && ((array[i] & 0xF) ^ 0xA) != 0; i++)
{
}
i++;
byte[] array2 = new byte[digest.GetDigestSize()];
int num3 = array.Length - num - array2.Length;
if (num3 - i <= 0)
{
return ReturnFalse(array);
}
if ((array[0] & 0x20) == 0)
{
fullMessage = true;
if (messageLength > num3 - i)
{
return ReturnFalse(array);
}
digest.Reset();
digest.BlockUpdate(array, i, num3 - i);
digest.DoFinal(array2, 0);
bool flag = true;
for (int j = 0; j != array2.Length; j++)
{
byte[] array4;
byte[] array3 = (array4 = array);
int num4 = num3 + j;
nint num5 = num4;
array3[num4] = (byte)(array4[num5] ^ array2[j]);
if (array[num3 + j] != 0)
{
flag = false;
}
}
if (!flag)
{
return ReturnFalse(array);
}
recoveredMessage = new byte[num3 - i];
Array.Copy(array, i, recoveredMessage, 0, recoveredMessage.Length);
}
else
{
fullMessage = false;
digest.DoFinal(array2, 0);
bool flag2 = true;
for (int k = 0; k != array2.Length; k++)
{
byte[] array4;
byte[] array5 = (array4 = array);
int num6 = num3 + k;
nint num5 = num6;
array5[num6] = (byte)(array4[num5] ^ array2[k]);
if (array[num3 + k] != 0)
{
flag2 = false;
}
}
if (!flag2)
{
return ReturnFalse(array);
}
recoveredMessage = new byte[num3 - i];
Array.Copy(array, i, recoveredMessage, 0, recoveredMessage.Length);
}
if (messageLength != 0 && !IsSameAs(mBuf, recoveredMessage))
{
return ReturnFalse(array);
}
ClearBlock(mBuf);
ClearBlock(array);
messageLength = 0;
return true;
}
private bool ReturnFalse(byte[] block)
{
messageLength = 0;
ClearBlock(mBuf);
ClearBlock(block);
return false;
}
public virtual bool HasFullMessage()
{
return fullMessage;
}
}