我用Python中的cryptography
库用公钥加密一个密钥。
key_path = "key.bin"
key = secrets.token_bytes(32)
with open(key_path, "w") as key_file:
key_file.write(key.hex())
with open(public_key, "rb") as public_key_file:
public_key = serialization.load_pem_public_key(public_key_file.read())
padding_config = padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
enc_path = key_path + ".enc"
with open(enc_path, "wb") as enc_file:
bytes_array = public_key.encrypt(content, padding_config)
enc_file.write(bytes_array)
这很好用,但是阅读这个键的代码是在Rust中,它只是一个对openssl C调用的FFI。openssl没有太多的选项。你不能选择“algorithm”,“mgf”和“label”。填充只是一个枚举,所以我选择了显而易见的PKCS1_OAEP
。
use openssl::{
cipher::Cipher,
cipher_ctx::CipherCtx,
pkey::Private,
rsa::{Padding, Rsa},
};
pub fn decrypt(key_file: File, pk: &str, pass: &str) -> String {
let rsa = Rsa::private_key_from_pem_passphrase(pk.as_bytes(), pass.as_bytes())
.expect("Can't build RSA object from PEM");
let mut encrypted = vec![];
key_file.read_to_end(&mut encrypted).expect("Can't read encrypted key file");
let mut decrypted: Vec<u8> = vec![0; rsa.size() as usize];
rsa.private_decrypt(&encrypted, &mut decrypted, Padding::PKCS1_OAEP).unwrap();
String::from_utf8(decrypted)
}
但我得到这个错误:
ErrorStack([
Error { code: 67571871, library: "rsa routines", function: "RSA_padding_check_PKCS1_type_2", reason: "pkcs decoding error", file: "../crypto/rsa/rsa_pk1.c", line: 251 },
Error { code: 67522674, library: "rsa routines", function: "rsa_ossl_private_decrypt", reason: "padding check failed", file: "../crypto/rsa/rsa_ossl.c", line: 500 }
])
我知道Rust代码是“正确的”,因为在以前的版本中,当我使用子进程调用openssl而不是cryptography
库时,它工作得很好(与Padding::PKCS1
一起)。
openssl documentation告诉我
RSA_PKCS1_OAEP_填充
PKCS #1 v2.0中定义的EME-OAEP,带有SHA-1、MGF 1和空编码参数。建议所有新应用程序使用此模式。
但是使用hashes.SHA1()
并没有改变任何东西。我应该如何设置我的padding以便openssl接受解密呢?
1条答案
按热度按时间9udxz4iz1#
据推测,发布的Rust代码使用RFC 8017默认值作为OAEP参数,即SHA-1作为内容摘要和MGF 1摘要,以及一个空标签。
另一方面,发布的Python代码对两个摘要都使用SHA-256,这就是为什么这两个代码不兼容的原因,你必须在Rust端将两个摘要都设置为SHA-256(或者你可以在Python端使用SHA-1)。
在这里,您可以找到一个用于OAEP的Rust sample implementation。OAEP填充的设置是使用
set_rsa_padding(Padding::PKCS1_OAEP)
完成的。要避免使用SHA-1默认值作为内容摘要,必须使用set_rsa_oaep_md(MessageDigest::sha256())
显式设置内容摘要。MGF 1摘要使用内容摘要隐式设置(因为在发布的示例中内容和MGF 1摘要是相同的,所以不需要在这里显式设置MGF 1摘要)。如果要使用不同的MGF 1摘要,则必须使用
set_rsa_mgf1_md()
。如果要设置标签,则必须使用set_rsa_oaep_label()
。但是,请注意,标签实际上始终为空(出于兼容性原因,也不应更改)。测试:使用发布的Python代码,base64编码的32字节密钥
加密方式如下(Base64编码):
注意,OAEP是不确定的,即用相同的密钥和明文重复加密产生不同的密文。
此密文可以用以下Rust代码解密: