Я новичок в том, как работает шифрование, однако меня попросили зашифровать и расшифровать значение с помощью шифрования Blowfish CBC. Теперь я потратил на это довольно много времени и думал, что все правильно, пока мне не прислали капельницу, которую они хотели бы использовать, что меня очень смутило. У меня создалось впечатление, что IV должен быть шестнадцатеричным значением, однако они прислали мне IV, который выглядит примерно так: cl5PxDOt.

Код, который мне удалось создать, выглядит так:

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 [], выход Int32, выкл.)

1
Bagzli 11 Фев 2021 в 19:35

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 аналоговым способом вместо текущей реализации.

1
Bagzli 11 Фев 2021 в 20:44