如何让 Rust 的 openssl crate 解密来自对称加密 gem 的数据,而不会出现 Node Crypto 自动删除的乱码?

2024-03-24

我正在使用 Rust 中的对称加密 gem 解密 Ruby on Rails 应用程序创建的遗留数据。请参阅我之前的问题如何用另一种语言解密由 Ruby 的“对称加密”gem 加密的数据? https://stackoverflow.com/questions/47661306/.

我已经在 Node 中实现了这个,其中加密库似乎知道如何去除 Rust 的加密字符串中的乱码。openssl crate https://crates.io/crates/openssl并没有剥离(至少,我使用它的方式)。我已经去掉了 PKCS7 填充和标头,但它仍然存在。那个官样文章是什么?我如何让 Rust 删除它?

加密数据以具有固定大小标头的明文形式开始,使用 AES-128-CBC 和 PKCS7 填充进行加密,然后进行 Base64 编码。使用 Node,我可以使用以下代码正确解密它:

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 不会按照我使用它的方式自动删除:

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"

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

起初我以为这 16 个字节的乱码来自于尝试解密 PKCS7 填充。但我可以验证填充已经被删除:如果我创建一个Crypter按照中的示例openssl板条箱的文档 https://docs.rs/openssl/0.10.4/openssl/symm/struct.Crypter.html,但不包括truncate()步骤,得到的结果Vec已连续12次12s — PKCS7 填充 — 已自动删除。

所以乱码不是 PKCS7 填充,但我不知道它是什么,也不知道如何使用 Rust 摆脱它。

并预见到米兰达关于如果我不是专家就不要乱搞加密的警告:这不会在生产中使用或创建数据以投入生产。


decipher.update 返回一个Buffer https://nodejs.org/api/crypto.html#crypto_decipher_update_data_inputencoding_outputencoding这在 Node 实现中被忽略。如果您更改 Node 实现以打印从更新调用返回的缓冲区,您可以看到它是相同的垃圾数据:

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

Outputs:

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

如果您更改 Rust 版本以忽略该输出部分,您将看到预期的输出:

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

Outputs:

[72, 97, 108, 102]
"Half"
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何让 Rust 的 openssl crate 解密来自对称加密 gem 的数据,而不会出现 Node Crypto 自动删除的乱码? 的相关文章

  • 我可以在 Rust 中将 const 与重载运算符一起使用吗?

    在此代码中 allow dead code use std ops Add struct Foo i32 const X i32 1 const Y i32 X X const A Foo Foo 1 const B Foo A A imp
  • 是否可以在纯 Rust 宏中编写像“print!”这样复杂的东西?

    我开始学习 Rust 宏 但文档有些有限 这很好 我想它们是一个专家功能 虽然我可以进行基本的代码生成 特征的实现等 但一些内置宏似乎远远超出了这些 例如各种打印宏 它们检查字符串文字并将其用于代码扩展 我在看的来源print https
  • 将 CryptoStream 解密为 MemoryStream

    我编写了一个过程 其中文件被加密并上传到 Azure 然后必须解密下载过程 这会失败并出现 填充无效且无法删除 错误 或 要解密的数据长度为无效的 错误 我在网上尝试了很多解决方案 包括C 使用 RijndaelManaged 和 Cryp
  • 带填充零的十六进制格式

    将整数类型格式化为十六进制字符串时 我无法让它用零填充数字 println 4x 0x0001 as u16 gt 0x1 but expected 0x0001 println 02x 0x0001 as u16 gt 0x1 same
  • cipher.update在java中做什么?

    我正在实施 DES CBC 我很困惑什么cipher init cipher update and cipher dofinal做 我只是使用 init 来设置密钥dofinal得到结果 我不使用更新 那是对的吗 另外使用时结果有什么不同U
  • 在节点上生成 AES 密钥

    我正在处理一个使用自定义协议来加密通信的遗留应用程序 随机 AES 密钥在旧版 Java 应用程序中生成 如下所示 keygen KeyGenerator getInstance AES keygen init 128 keygen gen
  • 扭曲和响应类型以及特征对象?

    我有一个扭曲拒绝处理程序 我像这样使用它 recover handle rejection 它是这样声明的 pub async fn handle rejection err Rejection gt Result
  • Rust 中为什么有 mod 关键字?

    看完之后this https doc rust lang org book crates and modules html 我想知道为什么有一个mod关键字和mod rs 我假设目录层次结构也可以描述模块 必须显式声明模块有几个原因 模块可
  • 类型“A”没有实现特征“A”

    我正在尝试使用一个具有以闭包作为参数的函数的特征 然后在特征对象上使用它 trait A fn f p self p P where P Fn gt struct B a Box a impl B fn c self self a f 该代
  • 如何将动态格式字符串与格式一起使用!宏?

    我想使用format 宏与String作为第一个参数 但因为宏需要字符串文字 所以我无法传递任何与它不同的内容 我想这样做是为了将字符串动态添加到当前字符串中 以便在视图引擎中使用 如果有更好的方法 我愿意接受建议 let test Str
  • 如何在 HashSet 或 HashMap 中使用自定义哈希函数?

    由于 SipHasher 对于我的用例来说太慢 因此我尝试实现自定义哈希函数 我发现一个例子 https github com rust lang rust blob master src librustc util nodemap rs我
  • AES 在汇编中的实现 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 大家好 我正在尝试构建一个代码来演示
  • 令人困惑的无法访问模式错误

    在使用 Rust 编译器时 我遇到了一条非常令人困惑的错误消息match陈述 enum Name Known fn unreachable pattern n Name gt usize use Name match n Unknown g
  • rust-analyzer 未能发现 vscode 中的工作区

    我开始学习 Rust 语言 但有一个问题rust analyzervscode 扩展名 它不提供代码完成 如链接所示 https rust analyzer github io manual html magic completions h
  • 如何为命令 stdout 添加 [stdout] 和 [stderr] 前缀?

    使用命令结构 https doc rust lang org std process struct Command html 如何向 stdout 和 stderr 缓冲区添加前缀 我希望输出看起来像这样 stdout things are
  • Rust 为什么要费心“let”? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我对 Rust 很感兴趣 所以我开始阅读 Rust 网站上的 Rust 编程指南 发现变量是通过以下方式声明的 let x i32 5 这意味着
  • 如何将字符迭代器转换为字符串?

    我需要类似的东西 collect 但这会产生String而不是容器chars 即我需要一个倒数chars https doc rust lang org std string struct String html method chars
  • Rust 编程竞赛中最快的惯用 I/O 例程?

    我的问题已部分得到解答 因此我根据从评论和其他实验中学到的知识对其进行了修改 总之 我想要一个用于编程竞赛的快速 I O 例程 其中使用单个文件解决问题 无需外部包 它应该从一个以空格分隔的标记序列中读取BufRead 标准输入或文件 标记
  • 在不同端口上运行多个 actix 应用程序

    我正在尝试运行两个应用程序 一个在端口 3006 上进行管理 另一个在端口 8080 上提供数据 他们共享数据库池 缓存 对于 actix 1 0 我可以这样做 我不知道这是否是最好的方法 let server Server build F
  • 使用 serde 序列化时如何对 HashMap 键进行排序?

    我正在连载一个HashMap与 serde 一样 如下所示 derive Serialize Deserialize struct MyStruct map HashMap

随机推荐

  • Glassfish 中的 JNDI 配置/查找

    我在 Glassfish 中获取一些基本的 JNDI 配置时遇到问题 我认为应该是一个简单的任务 在运行时确定特定属性是否设置为 true 我认为这是 JNDI 的一个很好的应用程序 但似乎无法在应用程序服务器和我的 servlet 代码之
  • 为什么自定义的基于 nib 的表格单元格的 init 方法没有被调用

    我有一个在界面生成器中创建的基于笔尖的表格视图单元 我将表视图单元格的类设置为FooTableViewCell它延伸自UITableViewCell In FooTableViewCell我像这样重写 init 方法 id init if
  • UITableViewRowAction 标题图像

    我做了一个自定义的 UITableViewRowAction 现在我想添加图像而不是文本 我知道这是可能的 但不知道该怎么做 你们中有人知道如何在 Swift 中执行此操作并愿意帮助我吗 感谢您的回答 iOS 11 0 Swift Appl
  • 解释一下c中qsort()函数的类型转换? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 1 在这段代码中pLhs and pRhs指向某个随机内存位置 那么如何将该随机内存位置的内容复制到 LHS 指向的位置 2 解释使用的比较
  • bash 脚本中变量的转义

    我的 bash 脚本使用 printf 编写了另一个 bash 脚本 printf bin bash HOME server file gromacs file name basename file date date m d Y for
  • 伊2。访问更高级别的文件夹

    简单的问题 我用Yii2高级模板 在apache I have DocumentRoot path www yii application1 frontend web 我怎样才能访问 www yii application1 uploads
  • 如何在没有日志、没有信息的情况下调试 Laravel 错误 500

    我正在开发现有的 Laravel 应用程序以开发新功能 但在我的计算机上安装该应用程序后 出现错误 500 并且没有任何线索来解决它 在我的 app php 文件中我设置了 env gt env APP ENV local debug gt
  • 是否建议在一个文件中包含多个类? [复制]

    这个问题在这里已经有答案了 可能的重复 我应该在一个文件中放入多少个 Python 类 https stackoverflow com questions 106896 how many python classes should i pu
  • Rails 3 检查属性是否更改

    在 Rails 3 中更新之前需要检查属性块是否已更改 街道 1 街道 2 城市 州 邮政编码 我知道我可以使用类似的东西 if user street1 params user street1 then do something end
  • R中似乎不存在错误光栅文件

    由于 pgirmess 包出现故障 我重新安装了 R 我已经重新下载了所有必需的软件包 我使用了在重新安装之前运行良好的相同脚本 但是我无法读取光栅对象 并且收到一条消息 Error file exists filename is not
  • 更新未屏蔽的 numpy 数组

    我的问题是双重的 首先 假设我有两个 numpy 数组 它们被部分屏蔽 array old 10 11 12 14 17 array update 5 9 15 8 13 19 16 如何创建一个新数组 其中所有非屏蔽值都被更新或修改 例如
  • Python easygui 无法选择文件

    这是我的代码 import easygui f easygui fileopenbox print f 看起来很简单 但是当我运行它时 我无法选择任何文件 请参见链接中的图 抱歉 如果这很愚蠢 但我已经无计可施了 https i stack
  • 安装国际 PHP 扩展 OSX High Sierra

    如何在 PHP 7 1 7 中安装 intl PHP 扩展 随 osx high Sierra 一起提供 所以我有完全相同的问题 正如其他人在这里评论所指出的 High Sierra 附带安装了 PHP 7 1 并且该 PHP 版本已对其进
  • Flutter TextField 输入验证日期

    我正在尝试编写一个日期输入控件 它接受像 23 12 1997 这样的日期 我希望它做的是自动为用户插入 字符 因此 当他们输入 23 时 监听器返回 23 以便他们可以输入 12 此时 监听器再次添加 让用户通过输入 1997 来完成日期
  • 如何将node.js连接到mysql和wamp/xampp服务器?

    我是一名 PHP 程序员 目前从事 WP CI OC 工作 我是node js的绝对初学者 想知道如何一步步连接MySql和WAMP XAMPP 如果我要直播 那么直播服务器的设置是什么 请让我知道一步一步的方法 按照本教程进行操作 教程在
  • 如何使用计时器移动顶点着色器中的点

    我无法弄清楚如何使用顶点着色器通过计时器为我的对象设置动画 我在窗口中的随机位置有一堆点 我想要做的是将这些点移动到窗口的中心 即 0 0 0 0 然后在某个点到达窗口中心后停止在那里 这是我的顶点着色器代码 layout location
  • 使用 PhoneGap / Cordova 的 Web 应用程序的状态栏通知

    我正在使用最新版本的 PhoneGap 开发适用于 iOS 和 Android 的 Web 应用程序 我想在手机状态栏上向用户发送通知 但我不知道该怎么做 似乎曾经存在过一个 Cordova 插件 StatusBarNotification
  • 使用 Hibernate 验证日期

    我们有现有的酒店管理系统 我被要求在系统的 创建住宿 功能中添加日期验证 该对话框如下所示 结束日期 已经过验证 如下面的代码所示 这 FutureHibernate 中的注释确保日期是将来的日期 NotNull Future DateTi
  • 从调用 forEach() 数组方法的方法返回。 JavaScript

    我正在使用从 JavaScript 中的数组调用的 forEach 方法 当我写作时return 在为数组中的每个元素调用的方法内部的某处 我从为特定元素调用的方法中返回 仅此而已 但我真正想要的是从数组调用 forEach 的方法中返回
  • 如何让 Rust 的 openssl crate 解密来自对称加密 gem 的数据,而不会出现 Node Crypto 自动删除的乱码?

    我正在使用 Rust 中的对称加密 gem 解密 Ruby on Rails 应用程序创建的遗留数据 请参阅我之前的问题如何用另一种语言解密由 Ruby 的 对称加密 gem 加密的数据 https stackoverflow com qu