Java BC SicBlockCipher直接输出等效于c# [英] Java BC SicBlockCipher direct output equivalent in c#

查看:153
本文介绍了Java BC SicBlockCipher直接输出等效于c#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用C#实现一些东西,为此我有一个单独的规范和相当清楚的理解我需要做什么,但同时作为参考我有一个Java实现,并希望遵循Java实现这种情况尽可能接近。

I am implementing something in C#, for which I have a separate spec and fairly clear understanding of what I need to do, but at the same time as a reference I have a Java implementation and would like to follow the Java implementation in this case as close as I can.

代码涉及加密流,Java源代码是这里
相关行在这里:

The code involves an encrypted stream and the Java source is here The relevant lines are here:

  private final StreamCipher enc;
...
  BlockCipher cipher;
  enc = new SICBlockCipher(cipher = new AESEngine());
  enc.init(true, new ParametersWithIV(new KeyParameter(secrets.aes), new byte[cipher.getBlockSize()]));
...
...
byte[] ptype = RLP.encodeInt((int) frame.type); //Result can be a single byte long
...
...
enc.processBytes(ptype, 0, ptype.length, buff, 0);
out.write(buff, 0, ptype.length); //encrypt and write a single byte from the SICBlockCipher stream

上面的Java BouncyCastle SicBlockCipher StreamCipher ,允许处理小于Aes块大小的单个或少量字节。

The above Java BouncyCastle SicBlockCipher is a StreamCipher and allows processing a single or small number of bytes less than the Aes block size.

在c#BouncyCastle中, SicBlockCipher 仅提供ProcessBlock,而BufferedBlockCipher似乎没有提供保证输出的方法ProcessBytes。

In c# BouncyCastle the SicBlockCipher only offers ProcessBlock and BufferedBlockCipher does not seem to offer a way of guaranteeing an output using ProcessBytes.

我需要使用C#BouncyCastle库来实现相同的功能吗?

What do I need to do with C# BouncyCastle library to achieve the equivalent functionality?

推荐答案

不幸的是, SicBlockCipher 本身并未实现为流密码,因此(实际上)此功能无法直接使用。

Unfortunately the SicBlockCipher itself is not implemented as a stream cipher, so this functionality is (indeed) not available directly.

BufferedBlockCipher ,其中考虑了许多不同的操作模式。它缓冲输入,而对于 SicBlockCipher 实现的计数器(CTR)模式,则需要缓冲加密的计数器块。

BufferedBlockCipher has been created with many different modes of operation in mind. It buffers the input, while for counter (CTR) mode which SicBlockCipher implements, you would need to buffer the encrypted counter blocks instead.

加密的计数器块组成密钥流,然后可以与明文进行异或,以创建密码流(或者实际上,使用密文来再次检索明文,加密是计数器模式的解密)。

The encrypted counter blocks make up the key stream, which can then be XOR'ed with the plaintext to create the cipherstream (or indeed, with the ciphertext to retrieve the plaintext again, encryption is decryption for counter mode).

我看到如何做到这一点的唯一方法是创建自己的 IBlockCipher实现并实现所述功能。

The only way I see how to do this is to create your own implementation of IBlockCipher and implement said functionality.

这是计数器模式作为流密码......

Here is the counter mode as stream cipher...

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Modes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SicStream
{
    public class SicStreamCipher : IStreamCipher
    {
        private SicBlockCipher parent;
        private int blockSize;

        private byte[] zeroBlock;

        private byte[] blockBuffer;
        private int processed;

        public SicStreamCipher(SicBlockCipher parent)
        {
            this.parent = parent;
            this.blockSize = parent.GetBlockSize();

            this.zeroBlock = new byte[blockSize];

            this.blockBuffer = new byte[blockSize];
            // indicates that no bytes are available: lazy generation of counter blocks (they may not be needed)
            this.processed = blockSize;
        }

        public string AlgorithmName
        {
            get
            {
                return parent.AlgorithmName;
            }
        }

        public void Init(bool forEncryption, ICipherParameters parameters)
        {
            parent.Init(forEncryption, parameters);

            Array.Clear(blockBuffer, 0, blockBuffer.Length);
            processed = blockSize;
        }

        public void ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff)
        {
            int inputProcessed = 0;
            while (inputProcessed < length)
            {
                // NOTE can be optimized further
                // the number of available bytes can be pre-calculated; too much branching
                if (processed == blockSize)
                {
                    // lazilly create a new block of key stream
                    parent.ProcessBlock(zeroBlock, 0, blockBuffer, 0);
                    processed = 0;
                }

                output[outOff + inputProcessed] = (byte)(input[inOff + inputProcessed] ^ blockBuffer[processed]);

                processed++;
                inputProcessed++;
            }
        }

        public void Reset()
        {
            parent.Reset();

            Array.Clear(blockBuffer, 0, blockBuffer.Length);
            this.processed = blockSize;
        }

        public byte ReturnByte(byte input)
        {
            if (processed == blockSize)
            {
                // lazily create a new block of key stream
                parent.ProcessBlock(zeroBlock, 0, blockBuffer, 0);
                processed = 0;
            }
            return (byte)(input ^ blockBuffer[processed++]);
        }
    }
}

......在这里被包装,以便可以在使用分组密码操作模式的代码中进行改装...

... and here it is wrapped so that it can be retrofitted in code where a block cipher mode of operation is used ...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Modes;

namespace SicStream
{
    /**
     * A class that implements an online Sic (segmented integer counter mode, or just counter (CTR) mode for short).
     * This class buffers one encrypted counter (representing the key stream) at a time.
     * The encryption of the counter is only performed when required, so that no key stream blocks are generated while they are not required.
     */
    public class StreamingSicBlockCipher : BufferedCipherBase
    {
        private SicStreamCipher parent;
        private int blockSize;

        public StreamingSicBlockCipher(SicBlockCipher parent)
        {
            this.parent = new SicStreamCipher(parent);
            this.blockSize = parent.GetBlockSize();
        }

        public override string AlgorithmName
        {
            get
            {
                return parent.AlgorithmName;
            }
        }

        public override byte[] DoFinal()
        {
            // returns no bytes at all, as there is no input
            return new byte[0];
        }

        public override byte[] DoFinal(byte[] input, int inOff, int length)
        {
            byte[] result = ProcessBytes(input, inOff, length);

            Reset();

            return result;
        }

        public override int GetBlockSize()
        {
            return blockSize;
        }

        public override int GetOutputSize(int inputLen)
        {
            return inputLen;
        }

        public override int GetUpdateOutputSize(int inputLen)
        {
            return inputLen;
        }

        public override void Init(bool forEncryption, ICipherParameters parameters)
        {
            parent.Init(forEncryption, parameters);
        }

        public override byte[] ProcessByte(byte input)
        {
            return new byte[] { parent.ReturnByte(input) };
        }

        public override byte[] ProcessBytes(byte[] input, int inOff, int length)
        {
            byte[] result = new byte[length];
            parent.ProcessBytes(input, inOff, length, result, 0);
            return result;
        }

        public override void Reset()
        {
            parent.Reset();
        }
    }
}

请注意,最后一个代码是效率较低,因为需要创建额外的数组。

Note that the last code is less efficient because of the additional arrays that need to be created.

这篇关于Java BC SicBlockCipher直接输出等效于c#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆