我如何获得Rust的openssl板条箱从对称加密gem解密数据,而又没有Node Crypto自动删除的垃圾? [英] How do I get Rust's openssl crate to decrypt data from the symmetric-encryption gem without the gibberish that Node Crypto automatically removes?

查看:228
本文介绍了我如何获得Rust的openssl板条箱从对称加密gem解密数据,而又没有Node Crypto自动删除的垃圾?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Rust中的对称加密gem解密Ruby on Rails应用程序创建的旧数据。参见我先前的问题如何解密由Ruby的对称加密 gem用另一种语言加密的数据?

I'm decrypting legacy data created by a Ruby on Rails application using the symmetric-encryption gem in Rust. See my earlier question How do I decrypt data encrypted by Ruby's `symmetric-encryption` gem in another language?.

我已经在Node中实现了这一点,其中的加密库似乎知道如何在Rust的 openssl 板条箱并没有删除(至少是我使用它的方式)。我已经去除了PKCS7填充和标头,但它仍然存在。那是什么鬼话,我如何让Rust删除它?

I've already implemented this in Node where the crypto library seems to know how to strip out gibberish in an encrypted string that Rust's openssl crate isn't stripping out (at least, the way I'm using it). I have already stripped out the PKCS7 padding and a header, yet it's still there. What is that gobbledygook, and how do I get Rust to remove it?

加密数据以带有固定大小报头的纯文本开始,使用AES-128-具有PKCS7填充的CBC,然后被Base64编码。使用Node,我可以使用以下代码对其正确解密:

The encrypted data began as plaintext with a fixed-size header, was encrypted using AES-128-CBC with PKCS7 padding, and was then Base64 encoded. Using Node, I can decrypt it correctly using the following code:

const crypto = require("crypto");

const KEY = Buffer.from("1234567890ABCDEF");
const IV = Buffer.from("1234567890ABCDEF");
const CIPHERTEXT = Buffer.from("QEVuQwBAEACuPUPByDkk5jyNzQ3Wd3xTy2Isihz62XTLe1M5qKQrvw==", "base64");
const HEADER_SIZE = 8;
const ALGO = "aes-128-cbc";

const decipher = crypto.createDecipheriv(ALGO, KEY, IV);

decipher.update(CIPHERTEXT.slice(HEADER_SIZE));
const result = decipher.final();

console.log([...result]);
console.log(result.toString());

结果是

[ 72, 97, 108, 102 ]
Half

我更喜欢在正在编写的应用程序中使用Rust。使用 openssl 条板箱,我可以解码加密的数据,但是Node的库知道如何剥离一堆垃圾,但是Rust不会像我那样自动剥离使用它:

I'd prefer to use Rust for the application I'm writing. Using the openssl crate, I can decode the encrypted data, but there's a bunch of junk that Node's library knows how to strip but Rust isn't stripping automatically the way I'm using it:

extern crate base64;
extern crate openssl;

use openssl::symm::*;

const KEY: &'static [u8] = b"1234567890ABCDEF";
const IV: &'static [u8] = b"1234567890ABCDEF";
const CIPHERTEXT: &'static str = "QEVuQwBAEACuPUPByDkk5jyNzQ3Wd3xTy2Isihz62XTLe1M5qKQrvw==";
const HEADER_SIZE: usize = 8;

fn main() {
    let decoded = base64::decode(&CIPHERTEXT).unwrap();
    let ciphertext = &decoded[HEADER_SIZE..];

    let result = decrypt(Cipher::aes_128_cbc(), KEY, Some(IV), ciphertext).unwrap();
    println!("{:?}", result);
    println!("{:?}", String::from_utf8_lossy(&result));
}

这里的结果是

[221, 75, 14, 215, 54, 120, 246, 222, 194, 208, 53, 68, 127, 190, 124, 8, 72, 97, 108, 102]
"�K\u{e}�6x����5D\u{7f}�|\u{8}Half"

您可以看到最后四个字节是正确的,但是Node删除了前面的16个字节应该有。我不知道这些字节是什么。

You can see that the last four bytes are correct, but that Node stripped out the preceding 16 bytes, as it appears it should have. I don't know what those bytes are.

起初,我认为16个字节的乱码是试图解密PKCS7填充的。但是我可以验证填充是否已被删除:如果我按照 openssl 板条箱中的示例创建 Crypter 文档,但不包括 truncate()步骤,生成的 Vec 具有12个连续的 12 s&mdash ; PKCS7填充—会自动删除。

At first I thought the 16 bytes of gibberish were from attempting to decrypt the PKCS7 padding. But I can verify that the padding was already stripped out: if I create a Crypter following the example in the openssl crate's documentation, but don't include the truncate() step, the resulting Vec has 12 consecutive 12s—the PKCS7 padding—that were automatically removed.

因此,胡言乱语不是PKCS7填充,但我不知道它是什么或如何使用Rust摆脱它。

So the gibberish is not PKCS7 padding, but I don't know what it is or how to get rid of it using Rust.

并且如果我不是专家,可以预见Miranda关于不要使用加密技术的警告:这将不会用于生产或创建要投入生产的数据。

And to anticipate the Miranda warning about not futzing with crypto if I'm not an expert: this is not going to be used in production or to create data to put into production.

推荐答案

decipher.update 返回 Buffer ,在Node实现中将其忽略。如果更改Node实现以打印从更新调用返回的缓冲区,则可以看到它是相同的垃圾数据:

decipher.update returns a Buffer which is ignored in the Node implementation. If you change the Node implementation to print the buffer returned from the update call, you can see that it's the same garbage data:

const buffer = decipher.update(CIPHERTEXT.slice(HEADER_SIZE));
console.log(buffer.toString());

输出:

�K�6x����5D�|

如果您也更改了Rust版本以忽略输出的那一部分,则会看到预期的输出:

If you change the Rust version to ignore that portion of the output as well, you see the expected output:

extern crate base64;
extern crate openssl;

use openssl::symm::*;

const KEY: &'static [u8] = b"1234567890ABCDEF";
const IV: &'static [u8] = b"1234567890ABCDEF";
const CIPHERTEXT: &'static str = "QEVuQwBAEACuPUPByDkk5jyNzQ3Wd3xTy2Isihz62XTLe1M5qKQrvw==";
const HEADER_SIZE: usize = 8;

fn main() {
    let decoded = base64::decode(&CIPHERTEXT).unwrap();
    let ciphertext = &decoded[HEADER_SIZE..];

    let t = Cipher::aes_128_cbc();
    let mut d = Crypter::new(t, Mode::Decrypt, KEY, Some(IV)).unwrap();
    let mut result = vec![0; CIPHERTEXT.len() + t.block_size()];
    d.update(&ciphertext, &mut result).unwrap();
    let len = d.finalize(&mut result).unwrap();
    result.truncate(len);
    println!("{:?}", result);
    println!("{:?}", String::from_utf8_lossy(&result));
}

输出:

[72, 97, 108, 102]
"Half"

这篇关于我如何获得Rust的openssl板条箱从对称加密gem解密数据,而又没有Node Crypto自动删除的垃圾?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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