gpt4 book ai didi

Java BC SicBlockCipher直接输出等价于c#

转载 作者:行者123 更新时间:2023-11-30 02:06:10 32 4
gpt4 key购买 nike

我正在用 C# 实现一些东西,对此我有一个单独的规范,并且对我需要做什么有相当清楚的了解,但同时作为引用,我有一个 Java 实现,并且希望遵循以下中的 Java 实现我尽可能接近这个案例。

该代码涉及加密流,Java源代码为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 block 大小的单个或少量字节。

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

我需要使用 C# BouncyCaSTLe 库做什么才能实现等效功能?

最佳答案

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

BufferedBlockCipher 在创建时考虑了许多不同的操作模式。它缓冲输入,而对于 SicBlockCipher 实现的计数器 (CTR) 模式,您需要缓冲加密的计数器 block 。

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

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

<小时/>

这是流密码的计数器模式...

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++]);
}
}
}

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

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();
}
}
}

请注意,由于需要创建额外的数组,最后的代码效率较低。

关于Java BC SicBlockCipher直接输出等价于c#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51286633/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com