lnk_thrussh_libsodium/
lib.rs

1extern crate libc;
2#[macro_use]
3extern crate lazy_static;
4use libc::c_ulonglong;
5use libsodium_sys::*;
6
7lazy_static! {
8    static ref SODIUM: i32 = unsafe { sodium_init() };
9}
10
11pub mod chacha20 {
12    use super::*;
13    pub const NONCE_BYTES: usize = 8;
14    pub const KEY_BYTES: usize = 32;
15    pub struct Nonce(pub [u8; NONCE_BYTES]);
16    pub struct Key(pub [u8; KEY_BYTES]);
17    pub fn chacha20_xor(c: &mut [u8], n: &Nonce, k: &Key) {
18        lazy_static::initialize(&super::SODIUM);
19        unsafe {
20            crypto_stream_chacha20_xor(
21                c.as_mut_ptr(),
22                c.as_ptr(),
23                c.len() as c_ulonglong,
24                n.0.as_ptr(),
25                k.0.as_ptr(),
26            );
27        }
28    }
29
30    pub fn chacha20_xor_ic(c: &mut [u8], n: &Nonce, ic: u64, k: &Key) {
31        lazy_static::initialize(&super::SODIUM);
32        unsafe {
33            crypto_stream_chacha20_xor_ic(
34                c.as_mut_ptr(),
35                c.as_ptr(),
36                c.len() as c_ulonglong,
37                n.0.as_ptr(),
38                ic,
39                k.0.as_ptr(),
40            );
41        }
42    }
43}
44
45pub mod poly1305 {
46    use super::*;
47    pub const KEY_BYTES: usize = 32;
48    pub const TAG_BYTES: usize = 16;
49    pub struct Key(pub [u8; KEY_BYTES]);
50    pub struct Tag(pub [u8; TAG_BYTES]);
51    pub fn poly1305_auth(m: &[u8], key: &Key) -> Tag {
52        lazy_static::initialize(&super::SODIUM);
53        let mut tag = Tag([0; TAG_BYTES]);
54        unsafe {
55            crypto_onetimeauth(
56                tag.0.as_mut_ptr(),
57                m.as_ptr(),
58                m.len() as c_ulonglong,
59                key.0.as_ptr(),
60            );
61        }
62        tag
63    }
64    pub fn poly1305_verify(tag: &[u8], m: &[u8], key: &Key) -> bool {
65        lazy_static::initialize(&super::SODIUM);
66        if tag.len() != TAG_BYTES {
67            false
68        } else {
69            unsafe {
70                crypto_onetimeauth_verify(
71                    tag.as_ptr(),
72                    m.as_ptr(),
73                    m.len() as c_ulonglong,
74                    key.0.as_ptr(),
75                ) == 0
76            }
77        }
78    }
79}
80
81pub mod ed25519 {
82    use super::*;
83    pub const PUBLICKEY_BYTES: usize = 32;
84    pub const SECRETKEY_BYTES: usize = 64;
85    pub const SIGNATURE_BYTES: usize = 64;
86
87    /// Ed25519 public key.
88    #[derive(Debug, PartialEq, Eq)]
89    pub struct PublicKey {
90        /// Actual key
91        pub key: [u8; PUBLICKEY_BYTES],
92    }
93
94    impl PublicKey {
95        pub fn new_zeroed() -> Self {
96            PublicKey {
97                key: [0; PUBLICKEY_BYTES],
98            }
99        }
100    }
101
102    /// Ed25519 secret key.
103    #[derive(Clone)]
104    pub struct SecretKey {
105        /// Actual key
106        pub key: [u8; SECRETKEY_BYTES],
107    }
108
109    impl SecretKey {
110        pub fn new_zeroed() -> Self {
111            SecretKey {
112                key: [0; SECRETKEY_BYTES],
113            }
114        }
115    }
116
117    pub struct Signature(pub [u8; SIGNATURE_BYTES]);
118
119    /// Generate a key pair.
120    pub fn keypair() -> (PublicKey, SecretKey) {
121        unsafe {
122            lazy_static::initialize(&super::SODIUM);
123            let mut pk = PublicKey {
124                key: [0; PUBLICKEY_BYTES],
125            };
126            let mut sk = SecretKey {
127                key: [0; SECRETKEY_BYTES],
128            };
129            crypto_sign_keypair(pk.key.as_mut_ptr(), sk.key.as_mut_ptr());
130            (pk, sk)
131        }
132    }
133
134    /// Verify a signature, `sig` could as well be a `Signature`.
135    pub fn verify_detached(sig: &[u8], m: &[u8], pk: &PublicKey) -> bool {
136        lazy_static::initialize(&super::SODIUM);
137        if sig.len() == SIGNATURE_BYTES {
138            unsafe {
139                crypto_sign_verify_detached(
140                    sig.as_ptr(),
141                    m.as_ptr(),
142                    m.len() as c_ulonglong,
143                    pk.key.as_ptr(),
144                ) == 0
145            }
146        } else {
147            false
148        }
149    }
150
151    /// Sign a message with a secret key.
152    pub fn sign_detached(m: &[u8], sk: &SecretKey) -> Signature {
153        lazy_static::initialize(&super::SODIUM);
154        let mut sig = Signature([0; SIGNATURE_BYTES]);
155        let mut sig_len = 0;
156        unsafe {
157            crypto_sign_detached(
158                sig.0.as_mut_ptr(),
159                &mut sig_len,
160                m.as_ptr(),
161                m.len() as c_ulonglong,
162                sk.key.as_ptr(),
163            );
164        }
165        sig
166    }
167}
168
169pub mod scalarmult {
170    use super::*;
171    pub const BYTES: usize = 32;
172
173    #[derive(Debug)]
174    pub struct Scalar(pub [u8; BYTES]);
175    #[derive(Debug)]
176    pub struct GroupElement(pub [u8; BYTES]);
177
178    pub fn scalarmult_base(n: &Scalar) -> GroupElement {
179        lazy_static::initialize(&super::SODIUM);
180        let mut q = GroupElement([0; BYTES]);
181        unsafe {
182            crypto_scalarmult_curve25519_base(q.0.as_mut_ptr(), n.0.as_ptr());
183        }
184        q
185    }
186
187    pub fn scalarmult(n: &Scalar, p: &GroupElement) -> GroupElement {
188        lazy_static::initialize(&super::SODIUM);
189        let mut q = GroupElement([0; BYTES]);
190        unsafe {
191            crypto_scalarmult_curve25519(q.0.as_mut_ptr(), n.0.as_ptr(), p.0.as_ptr());
192        }
193        q
194    }
195}