aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlloyd <[email protected]>2013-03-11 19:08:15 +0100
committerlloyd <[email protected]>2013-03-11 19:08:15 +0100
commitb0fd95676f36902a601bf95fb49d87ff474ef2a5 (patch)
tree43e9c1b8250a6bf83685a3ab4e1186aee922ca6d
parentExpose the submodules (diff)
downloadrust-openssl-b0fd95676f36902a601bf95fb49d87ff474ef2a5.tar.xz
rust-openssl-b0fd95676f36902a601bf95fb49d87ff474ef2a5.zip
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.
-rw-r--r--pkey.rs57
1 files changed, 42 insertions, 15 deletions
diff --git a/pkey.rs b/pkey.rs
index 5fe399b0..6b942d77 100644
--- a/pkey.rs
+++ b/pkey.rs
@@ -49,6 +49,19 @@ pub enum Role {
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 {
cast::reinterpret_cast(&rsa)
}
@@ -186,27 +199,22 @@ pub impl PKey {
len as uint - 41u
}
- /**
- * 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 {
+ fn encrypt_with_padding(s: &[u8], padding: EncryptionPadding) -> ~[u8] unsafe {
let rsa = libcrypto::EVP_PKEY_get1_RSA(self.evp);
let len = libcrypto::RSA_size(rsa);
- // 41 comes from RSA_public_encrypt(3) for OAEP
- assert s.len() < libcrypto::RSA_size(rsa) as uint - 41u;
+ assert s.len() < self.max_data();
let mut r = vec::from_elem(len as uint + 1u, 0u8);
do vec::as_mut_buf(r) |pr, _len| {
do vec::as_imm_buf(s) |ps, s_len| {
- // XXX: 4 == RSA_PKCS1_OAEP_PADDING
let rv = libcrypto::RSA_public_encrypt(
s_len as c_uint,
ps,
pr,
- rsa, 4 as c_int
+ rsa,
+ openssl_padding_code(padding)
);
if rv < 0 as c_int {
@@ -218,10 +226,7 @@ pub impl PKey {
}
}
- /**
- * Decrypts data, expecting OAEP padding, returning the decrypted data.
- */
- fn decrypt(s: &[u8]) -> ~[u8] unsafe {
+ fn decrypt_with_padding(s: &[u8], padding: EncryptionPadding) -> ~[u8] unsafe {
let rsa = libcrypto::EVP_PKEY_get1_RSA(self.evp);
let len = libcrypto::RSA_size(rsa);
@@ -231,13 +236,12 @@ pub impl PKey {
do vec::as_mut_buf(r) |pr, _len| {
do vec::as_imm_buf(s) |ps, s_len| {
- // XXX: 4 == RSA_PKCS1_OAEP_PADDING
let rv = libcrypto::RSA_private_decrypt(
s_len as c_uint,
ps,
pr,
rsa,
- 4 as c_int
+ openssl_padding_code(padding)
);
if rv < 0 as c_int {
@@ -250,6 +254,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(),
* can process an arbitrary amount of data; returns the signature.
*/
@@ -356,6 +371,18 @@ mod tests {
}
#[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]
fn test_sign() {
let k0 = PKey();
let k1 = PKey();