Add support for PKCS #1 v1.5 RSA encryption
Like it or not, needed for compatability with a lot of existing protocols. The default for encrypt/decrypt remains OAEP of course.
This commit is contained in:
parent
3ed6d865f0
commit
b0fd95676f
57
pkey.rs
57
pkey.rs
|
|
@ -49,6 +49,19 @@ pub enum Role {
|
||||||
Verify
|
Verify
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc = "Type of encryption padding to use."]
|
||||||
|
pub enum EncryptionPadding {
|
||||||
|
OAEP,
|
||||||
|
PKCS1v15
|
||||||
|
}
|
||||||
|
|
||||||
|
fn openssl_padding_code(padding: EncryptionPadding) -> c_int {
|
||||||
|
match padding {
|
||||||
|
OAEP => 4,
|
||||||
|
PKCS1v15 => 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn rsa_to_any(rsa: *RSA) -> *ANYKEY unsafe {
|
fn rsa_to_any(rsa: *RSA) -> *ANYKEY unsafe {
|
||||||
cast::reinterpret_cast(&rsa)
|
cast::reinterpret_cast(&rsa)
|
||||||
}
|
}
|
||||||
|
|
@ -186,27 +199,22 @@ pub impl PKey {
|
||||||
len as uint - 41u
|
len as uint - 41u
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
fn encrypt_with_padding(s: &[u8], padding: EncryptionPadding) -> ~[u8] unsafe {
|
||||||
* Encrypts data using OAEP padding, returning the encrypted data. The
|
|
||||||
* supplied data must not be larger than max_data().
|
|
||||||
*/
|
|
||||||
fn encrypt(s: &[u8]) -> ~[u8] unsafe {
|
|
||||||
let rsa = libcrypto::EVP_PKEY_get1_RSA(self.evp);
|
let rsa = libcrypto::EVP_PKEY_get1_RSA(self.evp);
|
||||||
let len = libcrypto::RSA_size(rsa);
|
let len = libcrypto::RSA_size(rsa);
|
||||||
|
|
||||||
// 41 comes from RSA_public_encrypt(3) for OAEP
|
assert s.len() < self.max_data();
|
||||||
assert s.len() < libcrypto::RSA_size(rsa) as uint - 41u;
|
|
||||||
|
|
||||||
let mut r = vec::from_elem(len as uint + 1u, 0u8);
|
let mut r = vec::from_elem(len as uint + 1u, 0u8);
|
||||||
|
|
||||||
do vec::as_mut_buf(r) |pr, _len| {
|
do vec::as_mut_buf(r) |pr, _len| {
|
||||||
do vec::as_imm_buf(s) |ps, s_len| {
|
do vec::as_imm_buf(s) |ps, s_len| {
|
||||||
// XXX: 4 == RSA_PKCS1_OAEP_PADDING
|
|
||||||
let rv = libcrypto::RSA_public_encrypt(
|
let rv = libcrypto::RSA_public_encrypt(
|
||||||
s_len as c_uint,
|
s_len as c_uint,
|
||||||
ps,
|
ps,
|
||||||
pr,
|
pr,
|
||||||
rsa, 4 as c_int
|
rsa,
|
||||||
|
openssl_padding_code(padding)
|
||||||
);
|
);
|
||||||
|
|
||||||
if rv < 0 as c_int {
|
if rv < 0 as c_int {
|
||||||
|
|
@ -218,10 +226,7 @@ pub impl PKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
fn decrypt_with_padding(s: &[u8], padding: EncryptionPadding) -> ~[u8] unsafe {
|
||||||
* Decrypts data, expecting OAEP padding, returning the decrypted data.
|
|
||||||
*/
|
|
||||||
fn decrypt(s: &[u8]) -> ~[u8] unsafe {
|
|
||||||
let rsa = libcrypto::EVP_PKEY_get1_RSA(self.evp);
|
let rsa = libcrypto::EVP_PKEY_get1_RSA(self.evp);
|
||||||
let len = libcrypto::RSA_size(rsa);
|
let len = libcrypto::RSA_size(rsa);
|
||||||
|
|
||||||
|
|
@ -231,13 +236,12 @@ pub impl PKey {
|
||||||
|
|
||||||
do vec::as_mut_buf(r) |pr, _len| {
|
do vec::as_mut_buf(r) |pr, _len| {
|
||||||
do vec::as_imm_buf(s) |ps, s_len| {
|
do vec::as_imm_buf(s) |ps, s_len| {
|
||||||
// XXX: 4 == RSA_PKCS1_OAEP_PADDING
|
|
||||||
let rv = libcrypto::RSA_private_decrypt(
|
let rv = libcrypto::RSA_private_decrypt(
|
||||||
s_len as c_uint,
|
s_len as c_uint,
|
||||||
ps,
|
ps,
|
||||||
pr,
|
pr,
|
||||||
rsa,
|
rsa,
|
||||||
4 as c_int
|
openssl_padding_code(padding)
|
||||||
);
|
);
|
||||||
|
|
||||||
if rv < 0 as c_int {
|
if rv < 0 as c_int {
|
||||||
|
|
@ -249,6 +253,17 @@ pub impl PKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypts data using OAEP padding, returning the encrypted data. The
|
||||||
|
* supplied data must not be larger than max_data().
|
||||||
|
*/
|
||||||
|
fn encrypt(s: &[u8]) -> ~[u8] unsafe { self.encrypt_with_padding(s, OAEP) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypts data, expecting OAEP padding, returning the decrypted data.
|
||||||
|
*/
|
||||||
|
fn decrypt(s: &[u8]) -> ~[u8] unsafe { self.decrypt_with_padding(s, OAEP) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Signs data, using OpenSSL's default scheme and sha256. Unlike encrypt(),
|
* Signs data, using OpenSSL's default scheme and sha256. Unlike encrypt(),
|
||||||
* can process an arbitrary amount of data; returns the signature.
|
* can process an arbitrary amount of data; returns the signature.
|
||||||
|
|
@ -355,6 +370,18 @@ mod tests {
|
||||||
assert(msg == dmsg);
|
assert(msg == dmsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_encrypt_pkcs() {
|
||||||
|
let k0 = PKey();
|
||||||
|
let k1 = PKey();
|
||||||
|
let msg = ~[0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
|
||||||
|
k0.gen(512u);
|
||||||
|
k1.load_pub(k0.save_pub());
|
||||||
|
let emsg = k1.encrypt_with_padding(msg, PKCS1v15);
|
||||||
|
let dmsg = k0.decrypt_with_padding(emsg, PKCS1v15);
|
||||||
|
assert(msg == dmsg);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sign() {
|
fn test_sign() {
|
||||||
let k0 = PKey();
|
let k0 = PKey();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue