【问题标题】:How to CBC Blowfish encrypt with non hex IV如何使用非十六进制 IV 进行 CBC Blowfish 加密
【发布时间】:2021-05-15 10:24:53
【问题描述】:

我对加密的工作原理相当陌生,但是,有人要求我使用 Blowfish CBC 加密来加密和解密一个值。现在我在这上面花了相当长的时间,我认为我做对了,直到他们把他们希望我使用的 IV 寄给我,这让我很困惑。我的印象是 IV 必须是十六进制值,但是,他们给我发了一个看起来类似于:cl5PxDOt 的 IV。

我设法生成的代码如下所示:

function Run()
{
    var key = "enter your key";
    var value = "Enter your test value";
    var iv = StringToByteArray("enter your 16 char hex value");

    var encryptedValue = CbcBlowfishEncrypt(value, key, iv);
    var decryptedValue = CbcBlowfishDecrypt(encryptedValue, key, iv);
}

private string CbcBlowfishEncrypt(string strValue, string key, byte[] iv)
{
    byte[] inputBytes = Encoding.UTF8.GetBytes(strValue);
    BlowfishEngine engine = new BlowfishEngine();
    CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
    PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher);
    KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(key));
    ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 8);

    cipher.Init(true, keyParamWithIV);
    byte[] outputBytes = new byte[cipher.GetOutputSize(inputBytes.Length)];
    int length = cipher.ProcessBytes(inputBytes, outputBytes, 0);
    cipher.DoFinal(outputBytes, length); //Do the final block
    var c = BitConverter.ToString(outputBytes);
    string encryptedInput = Convert.ToBase64String(outputBytes);
    var result = BitConverter.ToString(outputBytes).Replace("-", "");
    return result;
}

private string CbcBlowfishDecrypt(string strValue, string key, byte[] iv)
{
    BlowfishEngine engine = new BlowfishEngine();
    CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
    PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(blockCipher);
    KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(key));
    ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv, 0, 8);

    cipher.Init(false, keyParamWithIV);
    byte[] out1 = Hex.Decode(strValue);
    byte[] out2 = new byte[cipher.GetOutputSize(out1.Length)];
    int len2 = cipher.ProcessBytes(out1, 0, out1.Length, out2, 0);
    cipher.DoFinal(out2, len2);
    return Encoding.UTF8.GetString(out2);
}

public static byte[] StringToByteArray(string hex)
{
    return Enumerable.Range(0, hex.Length)
        .Where(x => x % 2 == 0)
        .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
        .ToArray();
}

我希望有人能告诉我如何修改上面的代码以使用以下示例 iv:cl5PxDOt

编辑:这是我尝试过的,但我每次都得到pad block corrupted

var newIv = "cl5PxDOt";
var newByteIv = newIv.ToArray().Select(Convert.ToByte).ToArray();
var newDecryptedValue = CbcBlowfishDecrypt(ospToken, key, newByteIv);
//var newDecryptedValue = Encoding.UTF8.GetBytes(newIv) -- Also tried this, but same result.

在 Org.BouncyCastle.Crypto.Paddings.Pkcs7Padding.PadCount(Byte[] 输入)
在 Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.DoFinal(Byte[] output, Int32 outOff)

【问题讨论】:

  • 尝试使用 IV 的 ASCII(UTF-8 工作)编码 - 与使用 strValue 相同。请注意,为了 CBC 模式的安全,CBC 的 IV 需要完全不可预测。哦,现代密码采用二进制输入,通常是字节。这与十六进制不同,十六进制通常用于以人类可读的形式表示这些字节。
  • @MaartenBodewes 抱歉,当您说要使用 UTF-8 时,我对您在谈论哪一行代码感到困惑?我的代码在cipher.DoFinal(out2, len2); 上崩溃了,这发生在我打电话给return Encoding.UTF8.GetString(out2);
  • IV 就是你说的对吧?对于 8 字节块密码,IV 现在是 8 个字符,您需要一个 8 字节 IV(用于 CBC)。因此,如果您将 1 个字符映射到 1 个字节,那么您将拥有正确的 IV 大小。 ASCII 会做到这一点,而 UTF-8 是 ASCII 的超集,因此考虑到字符串中的字符,它也能正常工作。
  • @MaartenBodewes 抱歉,我似乎还没有关注。您有机会发布代码示例吗?
  • 对不起,我现在在用LINux,手头没有C#环境...

标签: c# encryption bouncycastle blowfish cbc-mode


【解决方案1】:

如果密钥不是 Base64 解码而是 UTF-8 编码,即在CbcBlowfishDecrypt()(和CbcBlowfishEncrypt())行中,则可以解密密文

KeyParameter keyParam = new KeyParameter(Convert.FromBase64String(key));

将被替换为

KeyParameter keyParam = new KeyParameter(Encoding.UTF8.GetBytes(key));

UTF-8 编码的密钥长度为 448 位,因此是有效的密钥(Blowfish 定义为 32 到 448 位之间的密钥长度)。

IV 可以以模拟方式而不是当前实现方式进行 UTF-8 编码。

【讨论】:

  • 谢谢,这解决了我的问题。如果您不介意小请求,请从您的答案中删除明文。我不认为它是相关的,我不希望它公开显示。
  • 您知道在回答问题后如何开始并奖励赏金吗?我在任何地方都看不到选项。
  • @Bagzli - 我知道这是可能的,但我也不知道它是如何工作的。
猜你喜欢
  • 2020-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-09
  • 2017-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多