From 64106c4d3d4ddba8c7bc2af75376e6d3d3d75601 Mon Sep 17 00:00:00 2001
From:
Date: Mon, 29 Jun 2015 20:16:15 +0000
Subject: Update documentation
---
src/openssl/crypto/pkey.rs.html | 1103 +++++++++++++++++++++++++++++++++++++++
1 file changed, 1103 insertions(+)
create mode 100644 src/openssl/crypto/pkey.rs.html
(limited to 'src/openssl/crypto/pkey.rs.html')
diff --git a/src/openssl/crypto/pkey.rs.html b/src/openssl/crypto/pkey.rs.html
new file mode 100644
index 0000000..4b93f74
--- /dev/null
+++ b/src/openssl/crypto/pkey.rs.html
@@ -0,0 +1,1103 @@
+
+
+
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+
+use libc::{c_int, c_uint, c_ulong};
+use std::io;
+use std::io::prelude::*;
+use std::iter::repeat;
+use std::mem;
+use std::ptr;
+use bio::{MemBio};
+use crypto::hash;
+use crypto::hash::Type as HashType;
+use ffi;
+use ssl::error::{SslError, StreamError};
+
+#[derive(Copy, Clone)]
+pub enum Parts {
+ Neither,
+ Public,
+ Both
+}
+
+
+#[derive(Copy, Clone)]
+pub enum Role {
+ Encrypt,
+ Decrypt,
+ Sign,
+ Verify
+}
+
+
+#[derive(Copy, Clone)]
+pub enum EncryptionPadding {
+ OAEP,
+ PKCS1v15
+}
+
+fn openssl_padding_code(padding: EncryptionPadding) -> c_int {
+ match padding {
+ EncryptionPadding::OAEP => 4,
+ EncryptionPadding::PKCS1v15 => 1
+ }
+}
+
+fn openssl_hash_nid(hash: HashType) -> c_int {
+ match hash {
+ HashType::MD5 => 4,
+ HashType::SHA1 => 64,
+ HashType::SHA224 => 675,
+ HashType::SHA256 => 672,
+ HashType::SHA384 => 673,
+ HashType::SHA512 => 674,
+ HashType::RIPEMD160 => 117,
+ }
+}
+
+pub struct PKey {
+ evp: *mut ffi::EVP_PKEY,
+ parts: Parts,
+}
+
+
+impl PKey {
+ pub fn new() -> PKey {
+ unsafe {
+ ffi::init();
+
+ PKey {
+ evp: ffi::EVP_PKEY_new(),
+ parts: Parts::Neither,
+ }
+ }
+ }
+
+ pub fn from_handle(handle: *mut ffi::EVP_PKEY, parts: Parts) -> PKey {
+ ffi::init();
+ assert!(!handle.is_null());
+
+ PKey {
+ evp: handle,
+ parts: parts,
+ }
+ }
+
+
+ pub fn private_key_from_pem<R>(reader: &mut R) -> Result<PKey, SslError> where R: Read {
+ let mut mem_bio = try!(MemBio::new());
+ try!(io::copy(reader, &mut mem_bio).map_err(StreamError));
+
+ unsafe {
+ let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(),
+ ptr::null_mut(),
+ None, ptr::null_mut()));
+ Ok(PKey {
+ evp: evp,
+ parts: Parts::Both,
+ })
+ }
+ }
+
+ fn _tostr(&self, f: unsafe extern "C" fn(*mut ffi::RSA, *const *mut u8) -> c_int) -> Vec<u8> {
+ unsafe {
+ let rsa = ffi::EVP_PKEY_get1_RSA(self.evp);
+ let len = f(rsa, ptr::null());
+ if len < 0 as c_int { return vec!(); }
+ let mut s = repeat(0u8).take(len as usize).collect::<Vec<_>>();
+
+ let r = f(rsa, &s.as_mut_ptr());
+
+ s.truncate(r as usize);
+ s
+ }
+ }
+
+ fn _fromstr(&mut self, s: &[u8], f: unsafe extern "C" fn(*const *mut ffi::RSA, *const *const u8, c_uint) -> *mut ffi::RSA) {
+ unsafe {
+ let rsa = ptr::null_mut();
+ f(&rsa, &s.as_ptr(), s.len() as c_uint);
+ ffi::EVP_PKEY_set1_RSA(self.evp, rsa);
+ }
+ }
+
+ pub fn gen(&mut self, keysz: usize) {
+ unsafe {
+ let rsa = ffi::RSA_generate_key(
+ keysz as c_int,
+ 65537 as c_ulong,
+ ptr::null(),
+ ptr::null()
+ );
+
+
+ ffi::EVP_PKEY_assign(
+ self.evp,
+ 6 as c_int,
+ mem::transmute(rsa));
+
+ self.parts = Parts::Both;
+ }
+ }
+
+
+ pub fn save_pub(&self) -> Vec<u8> {
+ self._tostr(ffi::i2d_RSA_PUBKEY)
+ }
+
+
+ pub fn load_pub(&mut self, s: &[u8]) {
+ self._fromstr(s, ffi::d2i_RSA_PUBKEY);
+ self.parts = Parts::Public;
+ }
+
+
+ pub fn save_priv(&self) -> Vec<u8> {
+ self._tostr(ffi::i2d_RSAPrivateKey)
+ }
+
+ pub fn load_priv(&mut self, s: &[u8]) {
+ self._fromstr(s, ffi::d2i_RSAPrivateKey);
+ self.parts = Parts::Both;
+ }
+
+
+
+ pub fn write_pem<W: Write>(&self, writer: &mut W) -> Result<(), SslError> {
+ let mut mem_bio = try!(MemBio::new());
+ unsafe {
+ try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.get_handle(), self.evp, ptr::null(),
+ ptr::null_mut(), -1, None, ptr::null_mut()));
+
+ }
+ let mut buf = vec![];
+ try!(mem_bio.read_to_end(&mut buf).map_err(StreamError));
+ writer.write_all(&buf).map_err(StreamError)
+ }
+
+
+ pub fn size(&self) -> usize {
+ unsafe {
+ ffi::RSA_size(ffi::EVP_PKEY_get1_RSA(self.evp)) as usize
+ }
+ }
+
+
+ pub fn can(&self, r: Role) -> bool {
+ match r {
+ Role::Encrypt =>
+ match self.parts {
+ Parts::Neither => false,
+ _ => true,
+ },
+ Role::Verify =>
+ match self.parts {
+ Parts::Neither => false,
+ _ => true,
+ },
+ Role::Decrypt =>
+ match self.parts {
+ Parts::Both => true,
+ _ => false,
+ },
+ Role::Sign =>
+ match self.parts {
+ Parts::Both => true,
+ _ => false,
+ },
+ }
+ }
+
+
+ pub fn max_data(&self) -> usize {
+ unsafe {
+ let rsa = ffi::EVP_PKEY_get1_RSA(self.evp);
+ let len = ffi::RSA_size(rsa);
+
+
+ len as usize - 41
+ }
+ }
+
+ pub fn encrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec<u8> {
+ unsafe {
+ let rsa = ffi::EVP_PKEY_get1_RSA(self.evp);
+ let len = ffi::RSA_size(rsa);
+
+ assert!(s.len() < self.max_data());
+
+ let mut r = repeat(0u8).take(len as usize + 1).collect::<Vec<_>>();
+
+ let rv = ffi::RSA_public_encrypt(
+ s.len() as c_int,
+ s.as_ptr(),
+ r.as_mut_ptr(),
+ rsa,
+ openssl_padding_code(padding));
+
+ if rv < 0 as c_int {
+ vec!()
+ } else {
+ r.truncate(rv as usize);
+ r
+ }
+ }
+ }
+
+ pub fn decrypt_with_padding(&self, s: &[u8], padding: EncryptionPadding) -> Vec<u8> {
+ unsafe {
+ let rsa = ffi::EVP_PKEY_get1_RSA(self.evp);
+ let len = ffi::RSA_size(rsa);
+
+ assert_eq!(s.len() as c_int, ffi::RSA_size(rsa));
+
+ let mut r = repeat(0u8).take(len as usize + 1).collect::<Vec<_>>();
+
+ let rv = ffi::RSA_private_decrypt(
+ s.len() as c_int,
+ s.as_ptr(),
+ r.as_mut_ptr(),
+ rsa,
+ openssl_padding_code(padding));
+
+ if rv < 0 as c_int {
+ vec!()
+ } else {
+ r.truncate(rv as usize);
+ r
+ }
+ }
+ }
+
+
+ pub fn encrypt(&self, s: &[u8]) -> Vec<u8> { self.encrypt_with_padding(s, EncryptionPadding::OAEP) }
+
+
+ pub fn decrypt(&self, s: &[u8]) -> Vec<u8> { self.decrypt_with_padding(s, EncryptionPadding::OAEP) }
+
+
+ pub fn sign(&self, s: &[u8]) -> Vec<u8> { self.sign_with_hash(s, HashType::SHA256) }
+
+
+ pub fn verify(&self, h: &[u8], s: &[u8]) -> bool { self.verify_with_hash(h, s, HashType::SHA256) }
+
+
+ pub fn sign_with_hash(&self, s: &[u8], hash: hash::Type) -> Vec<u8> {
+ unsafe {
+ let rsa = ffi::EVP_PKEY_get1_RSA(self.evp);
+ let len = ffi::RSA_size(rsa);
+ let mut r = repeat(0u8).take(len as usize + 1).collect::<Vec<_>>();
+
+ let mut len = 0;
+ let rv = ffi::RSA_sign(
+ openssl_hash_nid(hash),
+ s.as_ptr(),
+ s.len() as c_uint,
+ r.as_mut_ptr(),
+ &mut len,
+ rsa);
+
+ if rv < 0 as c_int {
+ vec!()
+ } else {
+ r.truncate(len as usize);
+ r
+ }
+ }
+ }
+
+ pub fn verify_with_hash(&self, h: &[u8], s: &[u8], hash: hash::Type) -> bool {
+ unsafe {
+ let rsa = ffi::EVP_PKEY_get1_RSA(self.evp);
+
+ let rv = ffi::RSA_verify(
+ openssl_hash_nid(hash),
+ h.as_ptr(),
+ h.len() as c_uint,
+ s.as_ptr(),
+ s.len() as c_uint,
+ rsa
+ );
+
+ rv == 1 as c_int
+ }
+ }
+
+ pub unsafe fn get_handle(&self) -> *mut ffi::EVP_PKEY {
+ return self.evp
+ }
+
+ pub fn public_eq(&self, other: &PKey) -> bool {
+ unsafe { ffi::EVP_PKEY_cmp(self.evp, other.evp) == 1 }
+ }
+}
+
+impl Drop for PKey {
+ fn drop(&mut self) {
+ unsafe {
+ ffi::EVP_PKEY_free(self.evp);
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use std::path::Path;
+ use std::fs::File;
+ use crypto::hash::Type::{MD5, SHA1};
+
+ #[test]
+ fn test_gen_pub() {
+ let mut k0 = super::PKey::new();
+ let mut k1 = super::PKey::new();
+ k0.gen(512);
+ k1.load_pub(&k0.save_pub());
+ assert_eq!(k0.save_pub(), k1.save_pub());
+ assert!(k0.public_eq(&k1));
+ assert_eq!(k0.size(), k1.size());
+ assert!(k0.can(super::Role::Encrypt));
+ assert!(k0.can(super::Role::Decrypt));
+ assert!(k0.can(super::Role::Verify));
+ assert!(k0.can(super::Role::Sign));
+ assert!(k1.can(super::Role::Encrypt));
+ assert!(!k1.can(super::Role::Decrypt));
+ assert!(k1.can(super::Role::Verify));
+ assert!(!k1.can(super::Role::Sign));
+ }
+
+ #[test]
+ fn test_gen_priv() {
+ let mut k0 = super::PKey::new();
+ let mut k1 = super::PKey::new();
+ k0.gen(512);
+ k1.load_priv(&k0.save_priv());
+ assert_eq!(k0.save_priv(), k1.save_priv());
+ assert!(k0.public_eq(&k1));
+ assert_eq!(k0.size(), k1.size());
+ assert!(k0.can(super::Role::Encrypt));
+ assert!(k0.can(super::Role::Decrypt));
+ assert!(k0.can(super::Role::Verify));
+ assert!(k0.can(super::Role::Sign));
+ assert!(k1.can(super::Role::Encrypt));
+ assert!(k1.can(super::Role::Decrypt));
+ assert!(k1.can(super::Role::Verify));
+ assert!(k1.can(super::Role::Sign));
+ }
+
+ #[test]
+ fn test_private_key_from_pem() {
+ let key_path = Path::new("test/key.pem");
+ let mut file = File::open(&key_path)
+ .ok()
+ .expect("Failed to open `test/key.pem`");
+
+ super::PKey::private_key_from_pem(&mut file).unwrap();
+ }
+
+ #[test]
+ fn test_encrypt() {
+ let mut k0 = super::PKey::new();
+ let mut k1 = super::PKey::new();
+ let msg = vec!(0xdeu8, 0xadu8, 0xd0u8, 0x0du8);
+ k0.gen(512);
+ k1.load_pub(&k0.save_pub());
+ let emsg = k1.encrypt(&msg);
+ let dmsg = k0.decrypt(&emsg);
+ assert!(msg == dmsg);
+ }
+
+ #[test]
+ fn test_encrypt_pkcs() {
+ let mut k0 = super::PKey::new();
+ let mut k1 = super::PKey::new();
+ let msg = vec!(0xdeu8, 0xadu8, 0xd0u8, 0x0du8);
+ k0.gen(512);
+ k1.load_pub(&k0.save_pub());
+ let emsg = k1.encrypt_with_padding(&msg, super::EncryptionPadding::PKCS1v15);
+ let dmsg = k0.decrypt_with_padding(&emsg, super::EncryptionPadding::PKCS1v15);
+ assert!(msg == dmsg);
+ }
+
+ #[test]
+ fn test_sign() {
+ let mut k0 = super::PKey::new();
+ let mut k1 = super::PKey::new();
+ let msg = vec!(0xdeu8, 0xadu8, 0xd0u8, 0x0du8);
+ k0.gen(512);
+ k1.load_pub(&k0.save_pub());
+ let sig = k0.sign(&msg);
+ let rv = k1.verify(&msg, &sig);
+ assert!(rv == true);
+ }
+
+ #[test]
+ fn test_sign_hashes() {
+ let mut k0 = super::PKey::new();
+ let mut k1 = super::PKey::new();
+ let msg = vec!(0xdeu8, 0xadu8, 0xd0u8, 0x0du8);
+ k0.gen(512);
+ k1.load_pub(&k0.save_pub());
+
+ let sig = k0.sign_with_hash(&msg, MD5);
+
+ assert!(k1.verify_with_hash(&msg, &sig, MD5));
+ assert!(!k1.verify_with_hash(&msg, &sig, SHA1));
+ }
+
+ #[test]
+ fn test_eq() {
+ let mut k0 = super::PKey::new();
+ let mut p0 = super::PKey::new();
+ let mut k1 = super::PKey::new();
+ let mut p1 = super::PKey::new();
+ k0.gen(512);
+ k1.gen(512);
+ p0.load_pub(&k0.save_pub());
+ p1.load_pub(&k1.save_pub());
+
+ assert!(k0.public_eq(&k0));
+ assert!(k1.public_eq(&k1));
+ assert!(p0.public_eq(&p0));
+ assert!(p1.public_eq(&p1));
+ assert!(k0.public_eq(&p0));
+ assert!(k1.public_eq(&p1));
+
+ assert!(!k0.public_eq(&k1));
+ assert!(!p0.public_eq(&p1));
+ assert!(!k0.public_eq(&p1));
+ assert!(!p0.public_eq(&k1));
+ }
+}
+
+
+