【问题标题】:ARC4 encryption not working correctly server sideARC4 加密在服务器端无法正常工作
【发布时间】:2019-04-24 22:45:05
【问题描述】:

我有一个 socket.io 客户端,它可以相互发送数据,其中加密基于 ARC4。

我尝试了多种不同的场景,但始终无法解密任何内容,我不知道为什么。

班级:ARC4_New

    public class ARC4_New
    {
        private int i;
        private int j;
        private byte[] bytes;

        public const int POOLSIZE = 256;

        public ARC4_New()
        {
            bytes = new byte[POOLSIZE];
        }

        public ARC4_New(byte[] key)
        {
            bytes = new byte[POOLSIZE];
            this.Initialize(key);
        }

        public void Initialize(byte[] key)
        {
            this.i = 0;
            this.j = 0;

            for (i = 0; i < POOLSIZE; ++i)
            {
                this.bytes[i] = (byte)i;
            }

            for (i = 0; i < POOLSIZE; ++i)
            {
                j = (j + bytes[i] + key[i % key.Length]) & (POOLSIZE - 1);
                this.Swap(i, j);
            }

            this.i = 0;
            this.j = 0;
        }

        private void Swap(int a, int b)
        {
            byte t = this.bytes[a];
            this.bytes[a] = this.bytes[b];
            this.bytes[b] = t;
        }

        public byte Next()
        {
            this.i = ++this.i & (POOLSIZE - 1);
            this.j = (this.j + this.bytes[i]) & (POOLSIZE - 1);
            this.Swap(i, j);
            return this.bytes[(this.bytes[i] + this.bytes[j]) & 255];
        }

        public void Encrypt(ref byte[] src)
        {
            for (int k = 0; k < src.Length; k++)
            {
                src[k] ^= this.Next();
            }
        }

        public void Decrypt(ref byte[] src)
        {
            this.Encrypt(ref src);
        }
    }

        public System.Numerics.BigInteger RandomInteger(int bitSize)
        {
            var integerData = new byte[bitSize / 8];
            _numberGenerator.NextBytes(integerData);

            integerData[integerData.Length - 1] &= 0x7f;
            return new System.Numerics.BigInteger(integerData);
        }

我的生成密钥的脚本:

System.Numerics.BigInteger DHPrivate = RandomInteger(256);
System.Numerics.BigInteger DHPrimal = RandomInteger(256);
System.Numerics.BigInteger DHGenerated = RandomInteger(256);
if (DHGenerated > DHPrimal)
{
     System.Numerics.BigInteger tempG = DHGenerated;
     DHGenerated= DHPrimal;
     DHPrimal = tempG;
}

然后用这些值生成一个公钥:

System.Numerics.BigInteger DHPublic = System.Numerics.BigInteger.ModPow(DHGenerated, DHPrivate, DHPrimal);

然后我加密这个密钥:

string pkey = EncryptY(CalculatePublic, DHPublic);

(下面加密的附加代码)


        protected virtual string EncryptY(Func<System.Numerics.BigInteger, System.Numerics.BigInteger> calculator, System.Numerics.BigInteger value)
        {
            byte[] valueData = Encoding.UTF8.GetBytes(value.ToString());
            valueData = PKCSPad(valueData);

            Array.Reverse(valueData);
            var paddedInteger = new System.Numerics.BigInteger(valueData);

            System.Numerics.BigInteger calculatedInteger = calculator(paddedInteger);
            byte[] paddedData = calculatedInteger.ToByteArray();
            Array.Reverse(paddedData);

            string encryptedValue = Utils.Converter.BytesToHexString(paddedData).ToLower();
            return encryptedValue.StartsWith("00") ? encryptedValue.Substring(2) : encryptedValue;
        }

        protected virtual byte[] PKCSPad(byte[] data)
        {
            var buffer = new byte[128 - 1];
            int dataStartPos = (buffer.Length - data.Length);

            buffer[0] = (byte)Padding;
            Buffer.BlockCopy(data, 0, buffer, dataStartPos, data.Length);

            int paddingEndPos = (dataStartPos - 1);
            bool isRandom = (Padding == PKCSPadding.RandomByte);
            for (int i = 1; i < paddingEndPos; i++)
            {
                buffer[i] = (byte)(isRandom ?
                    _numberGenerator.Next(1, 256) : byte.MaxValue);
            }
            return buffer;
        }

毕竟我将字符串PKEY 发送到服务器。

服务器解密字符串后得到公钥,例如:127458393

当我使用:127458393 连接我的客户端和服务器时

喜欢:

BigInteger key = System.Numerics.BigInteger.Parse("127458393");
client = new ARC4_New(PrimalDing.ToByteArray());

我的客户发送如下字符串:

client.Encrypt(BYTE_HERE);

我的服务器读取如下:

client.Decrypt(BYTE_HERE);

但它失败了,并得到一个随机的不可读的字符串。

我在这里做错了什么?

【问题讨论】:

  • 我的猜测是 ARC4_NEW 脚本有问题,但我不确定,这是我第一次涉足这种代码风格..
  • 我建议 1) 为此使用已建立的加密库(如 Bouncy Castle),而不是自己滚动,即使您正在实施现有算法(不仅因为可能出现明显错误,而且尤其是以及允许旁道攻击的非显而易见的)和2)使用具有已知漏洞的算法,这是众所周知的RC4。如果您因为某个实现在某处要求它而被协议卡住,请考虑使用互操作代码与本机实现进行通信。速度较慢,但​​比重新实现更轻松。
  • 我会验证您在 Initialize 中获得的字节数组在两端是否相同。然后字节状态是相同的。我看不出有什么明显的错误; ++this.i 对我来说看起来很奇怪,我会使用 (this.i + 1) 以防万一这里发生奇怪的错误优化,但我对此表示怀疑。一端运行为 32 位,另一端运行为 64?我相信它们的优化方式不同。
  • @Rup 感谢您的回复,问题是我对“服务器”进行了反向工程,所以我只能修改客户端。顺便说一句,这两个应用程序都运行 64 位,遗憾的是,强制同时使用 32 位或 64 位并没有解决任何问题。问题是代码中没有错误,因为“闭源客户端”发送数据并且服务器很好地解密了它。我使用 100% 与服务器完全相同的 ARC4 类,因为该部分是开源的,但即使在客户端,当我使用以下命令解密时:client.Encrypt 和 client.Decrypt 它不会返回与加密前相同的值这就是这里的主要问题。
  • 应该吗?您需要为每个加密和解密创建一个新的 ARC4:它是一个流密码,因此您需要将流放在同一个地方 - 您不能只调用 client.Encrypt 然后 client.Decrypt 使用同一个客户端.

标签: c# encryption


【解决方案1】:

我设法解决了这个问题

出于某种原因,我的服务器曾经并且正在反转我在 ARC4 客户端中使用的字节..

所以我现在把它简单地反转为一个修补程序

System.Numerics.BigInteger temp = System.Numerics.BigInteger.Parse(textBox1.Text); client = new ARC4_New(temp.ToByteArray().Reverse().ToArray());

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-29
    • 2017-03-15
    • 2012-01-20
    • 2023-03-12
    • 2017-06-02
    • 1970-01-01
    • 1970-01-01
    • 2023-01-30
    相关资源
    最近更新 更多