libsignal_protocol/keys/
public.rs1use std::{
2 cmp::{Ord, Ordering},
3 ptr,
4};
5
6use failure::Error;
7
8use crate::{
9 errors::{FromInternalErrorCode, InternalError},
10 raw_ptr::Raw,
11 Context,
12};
13
14#[derive(Clone, Debug)]
16pub struct PublicKey {
17 pub(crate) raw: Raw<sys::ec_public_key>,
18}
19
20impl PublicKey {
21 pub fn decode_point(ctx: &Context, key: &[u8]) -> Result<PublicKey, Error> {
23 unsafe {
24 let mut raw = ptr::null_mut();
25 sys::curve_decode_point(
26 &mut raw,
27 key.as_ptr(),
28 key.len(),
29 ctx.raw(),
30 )
31 .into_result()?;
32
33 Ok(PublicKey {
34 raw: Raw::from_ptr(raw),
35 })
36 }
37 }
38
39 pub fn verify_signature(
41 &self,
42 message: &[u8],
43 signature: &[u8],
44 ) -> Result<(), Error> {
45 unsafe {
46 let result = sys::curve_verify_signature(
47 self.raw.as_const_ptr(),
48 message.as_ptr(),
49 message.len(),
50 signature.as_ptr(),
51 signature.len(),
52 );
53
54 if result == 1 {
55 Ok(())
56 } else if result == 0 {
57 Err(failure::err_msg("Invalid signature"))
58 } else if let Some(err) = InternalError::from_error_code(result) {
59 Err(err.into())
60 } else {
61 Err(failure::format_err!("Unknown error code: {}", result))
62 }
63 }
64 }
65}
66
67impl Ord for PublicKey {
68 fn cmp(&self, other: &PublicKey) -> Ordering {
69 let cmp = unsafe {
70 sys::ec_public_key_compare(
71 self.raw.as_const_ptr(),
72 other.raw.as_const_ptr(),
73 )
74 };
75
76 if cmp < 0 {
77 Ordering::Less
78 } else if cmp > 0 {
79 Ordering::Greater
80 } else {
81 Ordering::Equal
82 }
83 }
84}
85
86impl PartialEq for PublicKey {
87 fn eq(&self, other: &PublicKey) -> bool {
88 self.cmp(other) == Ordering::Equal
89 }
90}
91
92impl Eq for PublicKey {}
93
94impl PartialOrd for PublicKey {
95 fn partial_cmp(&self, other: &PublicKey) -> Option<Ordering> {
96 Some(self.cmp(other))
97 }
98}
99
100impl_serializable!(PublicKey, ec_public_key_serialize, asd);
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[cfg(any(feature = "crypto-native", feature = "crypto-openssl"))]
107 #[test]
108 fn decode_from_binary() {
109 cfg_if::cfg_if! {
110 if #[cfg(feature = "crypto-native")] {
111 type Crypto = crate::crypto::DefaultCrypto;
112 } else if #[cfg(feature = "crypto-openssl")] {
113 type Crypto = crate::crypto::OpenSSLCrypto;
114 } else {
115 compile_error!("These tests require one of the crypto features to be enabled");
116 }
117 }
118 let ctx = Context::new(Crypto::default()).unwrap();
119 let public = &[
120 0x05, 0x1b, 0xb7, 0x59, 0x66, 0xf2, 0xe9, 0x3a, 0x36, 0x91, 0xdf,
121 0xff, 0x94, 0x2b, 0xb2, 0xa4, 0x66, 0xa1, 0xc0, 0x8b, 0x8d, 0x78,
122 0xca, 0x3f, 0x4d, 0x6d, 0xf8, 0xb8, 0xbf, 0xa2, 0xe4, 0xee, 0x28,
123 ];
124
125 let _got = PublicKey::decode_point(&ctx, public).unwrap();
126 }
127}