1
//! Macros that can be used to improve your life with regards to crypto.
2

            
3
use derive_deftly::define_derive_deftly;
4

            
5
/// Create an ed25519 keypair wrapper given a visibility and a struct name.
6
///
7
/// # Syntax:
8
/// ```rust,ignore
9
/// define_ed25519_keypair(<visibility> <prefix>)
10
/// ```
11
///
12
/// This macro creates a struct tuple named `<prefix>Keypair` which contains the lower-level
13
/// cryptographic keypair for an ed25519 keypair. It derives the deftly Ed25519Keypair template
14
/// which in turn creates `<prefix>PublicKey` along a series of useful methods.
15
///
16
/// The keypair is NOT clonable by design in order to avoid duplicating secret key material.
17
///
18
/// # Example:
19
///
20
/// ```rust
21
/// use tor_key_forge::define_ed25519_keypair;
22
///
23
/// define_ed25519_keypair!(NonPublicSigning);
24
/// define_ed25519_keypair!(pub PublicSigning);
25
/// define_ed25519_keypair!(pub(crate) CratePublicSigning);
26
/// ```
27
///
28
/// The above results in `NonPublicSigningKeypair` and `NonPublicSigningPublicKey` struct being
29
/// created and usable with a series of useful methods. Same for the other defines.
30
///
31
/// You can then use these objects like so:
32
///
33
/// ```rust
34
/// # use tor_llcrypto::rng::FakeEntropicRng;
35
/// # let mut rng = FakeEntropicRng(rand::rng());
36
/// use rand::Rng;
37
/// use tor_key_forge::Keygen;
38
/// use tor_key_forge::define_ed25519_keypair;
39
/// use tor_llcrypto::pk::ValidatableSignature;
40
/// use tor_llcrypto::pk::ed25519::Ed25519SigningKey;
41
///
42
/// define_ed25519_keypair!(
43
///     /// Our signing key.
44
///     MySigning
45
/// );
46
///
47
/// let signing_kp = MySigningKeypair::generate(&mut rng).expect("Invalid keygen");
48
/// let signing_pubkey = signing_kp.public();
49
/// // Lets sign this wonderful message.
50
/// let message = "Workers want rights, not your opinion".as_bytes();
51
/// let sig = signing_kp.sign(&message);
52
///
53
/// // You can then verify either directly with the keypair or the public key.
54
/// assert!(signing_kp.verify(sig, &message));
55
/// assert!(signing_pubkey.verify(sig, &message));
56
/// ```
57
#[macro_export]
58
macro_rules! define_ed25519_keypair {
59
    ($(#[ $docs_and_attrs:meta ])*
60
     $vis:vis $base_name:ident) => {
61
        $crate::macro_deps::paste! {
62
            #[derive($crate::derive_deftly::Deftly)]
63
            #[derive_deftly($crate::macro_deps::Ed25519Keypair)]
64
            #[deftly(kp(pubkey = $base_name "PublicKey"))]
65
            #[non_exhaustive]
66
            $(#[ $docs_and_attrs ])*
67
            $vis struct [<$base_name "Keypair">]($crate::macro_deps::ed25519::Keypair);
68
        }
69
    };
70
}
71

            
72
define_derive_deftly! {
73
    /// Implement set of helper functions around a type wrapping an ed25519::Keypair.
74
    export Ed25519Keypair for struct:
75

            
76
    // Enforce that the object has a single field. We want to avoid the implementer to start
77
    // storing metadata or other things in this object that is meant specifically to be
78
    // a semantic wrapper around an Ed25519 keypair.
79
    ${if not(approx_equal(${for fields { 1 }}, 1)) { ${error "Single field only"}}}
80

            
81
    ${define KP_NAME $( $fname )}
82
    ${define PK_NAME ${tmeta(kp(pubkey)) as ident}}
83

            
84
    /// Public key component of this keypair. Useful if we move the public key around,
85
    /// it then keeps it semantic with the name and less prone to errors.
86
    #[derive(Clone, Debug, PartialEq, Eq)]
87
    #[derive($crate::macro_deps::derive_more::From, $crate::macro_deps::derive_more::Into)]
88
    #[non_exhaustive]
89
    $tvis struct $PK_NAME ($tvis $crate::macro_deps::ed25519::PublicKey);
90

            
91
    impl $PK_NAME {
92
        /// Verify the signature of a given message.
93
        #[allow(unused)]
94
        $tvis fn verify(&self, sig: $crate::macro_deps::ed25519::Signature, text: &[u8]) -> bool {
95
            use $crate::macro_deps::ValidatableSignature;
96
            $crate::macro_deps::ed25519::ValidatableEd25519Signature::new(self.0, sig, text).is_valid()
97
        }
98
    }
99

            
100
    impl $crate::macro_deps::ed25519::Ed25519PublicKey for $PK_NAME {
101
        fn public_key(&self) -> $crate::macro_deps::ed25519::PublicKey {
102
            self.0
103
        }
104
    }
105

            
106
    // We don't expect all implementations to use all code.
107
    #[allow(unused)]
108
    impl $ttype {
109
        /// Build the raw inner public key into the wrapper public key object.
110
2599
        $tvis fn public(&self) -> $PK_NAME {
111
            $PK_NAME((&self.$KP_NAME).into())
112
        }
113
        /// Verify the signature of a given message.
114
4
        $tvis fn verify(&self, sig: $crate::macro_deps::ed25519::Signature, text: &[u8]) -> bool {
115
            use $crate::macro_deps::ValidatableSignature;
116
            $crate::macro_deps::ed25519::ValidatableEd25519Signature::new(
117
                self.0.verifying_key(), sig, text
118
            ).is_valid()
119
        }
120
        /// Return a Ed25519Identity built from this keypair.
121
2401
        $tvis fn to_ed25519_id(&self) -> $crate::macro_deps::ed25519::Ed25519Identity {
122
            $crate::macro_deps::ed25519::Ed25519Identity::from(&self.public().0)
123
        }
124
    }
125

            
126
    impl From<$crate::macro_deps::ed25519::Keypair> for $ttype {
127
        fn from(kp: $crate::macro_deps::ed25519::Keypair) -> Self {
128
            Self(kp)
129
        }
130
    }
131
    impl $crate::macro_deps::ed25519::Ed25519PublicKey for $ttype {
132
1127
        fn public_key(&self) -> $crate::macro_deps::ed25519::PublicKey {
133
            self.0.public_key()
134
        }
135
    }
136

            
137
    impl $crate::macro_deps::ed25519::Ed25519SigningKey for $ttype {
138
1129
        fn sign(
139
1129
            &self,
140
1129
            msg: &[u8])
141
1129
        -> $crate::macro_deps::ed25519::Signature {
142
            self.0.sign(msg)
143
        }
144
    }
145

            
146
    /// Implementing EncodableItem, ToEncodableKey and Keygen allows this wrapper key to be stored
147
    /// in a keystore.
148

            
149
    impl $crate::ItemType for $ttype {
150
        fn item_type() -> $crate::KeystoreItemType {
151
            $crate::KeyType::Ed25519Keypair.into()
152
        }
153
    }
154

            
155
    impl $crate::EncodableItem for $ttype {
156
        fn as_keystore_item(&self) -> $crate::Result<$crate::KeystoreItem> {
157
            self.$KP_NAME.as_keystore_item()
158
        }
159
    }
160

            
161
    impl $crate::ToEncodableKey for $ttype {
162
        type Key = $crate::macro_deps::ed25519::Keypair;
163
        type KeyPair = $ttype;
164

            
165
        fn to_encodable_key(self) -> Self::Key {
166
            self.$KP_NAME
167
        }
168
3626
        fn from_encodable_key(key: Self::Key) -> Self {
169
            Self(key)
170
        }
171
    }
172

            
173
    impl $crate::Keygen for $ttype {
174
149
        fn generate(mut rng: &mut dyn $crate::KeygenRng) -> $crate::Result<Self>
175
149
        where
176
149
            Self: Sized
177
        {
178
            Ok(Self { $KP_NAME: $crate::macro_deps::ed25519::Keypair::generate(&mut rng) })
179
        }
180
    }
181
}
182

            
183
/// Create a curve25519 keypair wrapper given a visibility and a struct name.
184
///
185
/// # Syntax:
186
/// ```rust,ignore
187
/// define_curve25519_keypair(<visibility> <prefix>)
188
/// ```
189
///
190
/// This macro creates a struct tuple named `<prefix>Keypair` which contains the lower-level
191
/// cryptographic keypair for a curve25519 keypair. It derives the deftly Curve25519Keypair template
192
/// which in turn creates `<prefix>PublicKey` along a series of useful methods.
193
///
194
/// The keypair is NOT clonable by design in order to avoid duplicating secret key material.
195
///
196
/// # Example:
197
///
198
/// ```rust
199
/// use tor_key_forge::define_curve25519_keypair;
200
///
201
/// define_curve25519_keypair!(NonPublicEnc);
202
/// define_curve25519_keypair!(pub PublicEnc);
203
/// define_curve25519_keypair!(pub(crate) CratePublicEnc);
204
/// ```
205
///
206
/// The above results in `NonPublicEncKeypair` and `NonPublicEncPublicKey` struct being created and
207
/// usable with a series of useful methods.
208
///
209
/// You can then use these objects like so:
210
///
211
/// ```rust
212
/// # use tor_llcrypto::rng::FakeEntropicRng;
213
/// # let mut rng = FakeEntropicRng(rand::rng());
214
/// # use rand::Rng;
215
/// use tor_key_forge::define_curve25519_keypair;
216
/// use tor_key_forge::Keygen;
217
///
218
/// define_curve25519_keypair!(
219
///     // This is Alice's keypair.
220
///     AliceEnc
221
/// );
222
/// define_curve25519_keypair!(BobEnc);
223
///
224
/// let alice_kp = AliceEncKeypair::generate(&mut rng).expect("Failed alice keygen");
225
/// let bob_kp = BobEncKeypair::generate(&mut rng).expect("Failed bob keygen");
226
///
227
/// // Using the public key wrapper
228
/// let alice_shared_secret = alice_kp.diffie_hellman(bob_kp.public());
229
/// // Using the direct curve25519::PublicKey.
230
/// let bob_shared_secret = bob_kp.diffie_hellman(&alice_kp.public().0);
231
///
232
/// assert_eq!(alice_shared_secret.as_bytes(), bob_shared_secret.as_bytes());
233
/// ```
234
#[macro_export]
235
macro_rules! define_curve25519_keypair {
236
    ($(#[ $docs_and_attrs:meta ])*
237
    $vis:vis $base_name:ident) => {
238
        $crate::macro_deps::paste! {
239
            #[derive($crate::derive_deftly::Deftly)]
240
            #[derive_deftly($crate::macro_deps::Curve25519Keypair)]
241
            #[deftly(kp(pubkey = $base_name "PublicKey"))]
242
            #[non_exhaustive]
243
            $(#[ $docs_and_attrs ])*
244
            $vis struct [<$base_name "Keypair">]($crate::macro_deps::curve25519::StaticKeypair);
245
        }
246
    };
247
}
248

            
249
define_derive_deftly! {
250
    /// Implement set of helper functions around a type wrapping an ed25519::Keypair.
251
    export Curve25519Keypair for struct:
252

            
253
    // Enforce that the object has a single field. We want to avoid the implementer to start
254
    // storing metadata or other things in this object that is meant specifically to be
255
    // a semantic wrapper around an Curve25519 keypair.
256
    ${if not(approx_equal(${for fields { 1 }}, 1)) { ${error "Single field only"}}}
257

            
258
    ${define KP_NAME $( $fname )}
259
    ${define PK_NAME ${tmeta(kp(pubkey)) as ident}}
260

            
261
    /// Public key component of this keypair. Useful if we move the public key around,
262
    /// it then keeps it semantic with the name and less prone to errors.
263
    #[derive(Clone, Debug, PartialEq, Eq)]
264
    #[derive($crate::macro_deps::derive_more::From, $crate::macro_deps::derive_more::Into)]
265
    #[non_exhaustive]
266
    $tvis struct $PK_NAME ($crate::macro_deps::curve25519::PublicKey);
267

            
268
    impl std::borrow::Borrow<$crate::macro_deps::curve25519::PublicKey> for $PK_NAME {
269
        #[inline]
270
        fn borrow(&self) -> &$crate::macro_deps::curve25519::PublicKey {
271
            &self.0
272
        }
273
    }
274

            
275
    impl $PK_NAME {
276
        /// Get the inner [`PublicKey`]($crate::macro_deps::curve25519::PublicKey).
277
        // This can be nicer to use than
278
        // `<FooPublicKey as Borrow<curve25519::PublicKey>>::borrow(&foo)`.
279
        #[inline]
280
        $tvis fn inner(&self) -> &$crate::macro_deps::curve25519::PublicKey {
281
            &self.0
282
        }
283
    }
284

            
285
    impl $ttype {
286
        /// Build the raw inner public key into the wrapper public key object.
287
        $tvis fn public(&self) -> $PK_NAME {
288
            $PK_NAME(self.$KP_NAME.public.clone())
289
        }
290

            
291
        /// Wrapper around the diffie_hellman() function of the underlying type. This is pretty fun
292
        /// because it accepts both the PK_NAME wrapper or the raw inner curve25519::PublicKey.
293
        $tvis fn diffie_hellman<T>(&self, pk: T) -> $crate::macro_deps::curve25519::SharedSecret
294
        where
295
            T: std::borrow::Borrow<$crate::macro_deps::curve25519::PublicKey>
296
        {
297
            self.$KP_NAME.secret.diffie_hellman(pk.borrow())
298
        }
299
    }
300

            
301
    impl From<$crate::macro_deps::curve25519::StaticKeypair> for $ttype {
302
        fn from(kp: $crate::macro_deps::curve25519::StaticKeypair) -> Self {
303
            Self(kp)
304
        }
305
    }
306

            
307
    /// Implementing EncodableItem, ToEncodableKey and Keygen allows this wrapper key to be stored
308
    /// in a keystore.
309

            
310
    impl $crate::ItemType for $ttype {
311
        fn item_type() -> $crate::KeystoreItemType {
312
            $crate::KeyType::X25519StaticKeypair.into()
313
        }
314
    }
315

            
316
    impl $crate::EncodableItem for $ttype {
317
        fn as_keystore_item(&self) -> $crate::Result<$crate::KeystoreItem> {
318
            self.$KP_NAME.as_keystore_item()
319
        }
320
    }
321

            
322
    impl $crate::ToEncodableKey for $ttype {
323
        type Key = $crate::macro_deps::curve25519::StaticKeypair;
324
        type KeyPair = $ttype;
325

            
326
        fn to_encodable_key(self) -> Self::Key {
327
            self.$KP_NAME
328
        }
329
784
        fn from_encodable_key(key: Self::Key) -> Self {
330
            Self(key)
331
        }
332
    }
333

            
334
    impl $crate::Keygen for $ttype {
335
        fn generate(mut rng: &mut dyn $crate::KeygenRng) -> $crate::Result<Self>
336
        where
337
            Self: Sized
338
        {
339
            let secret = $crate::macro_deps::curve25519::StaticSecret::random_from_rng(rng);
340
            let public: $crate::macro_deps::curve25519::PublicKey = (&secret).into();
341
            let kp = $crate::macro_deps::curve25519::StaticKeypair {
342
                secret: secret.into(),
343
                public: public.into(),
344
            };
345
            Ok(kp.into())
346
        }
347
    }
348
}
349

            
350
/// Create an RSA keypair wrapper given a visibility and a struct name.
351
///
352
/// # Syntax:
353
/// ```rust,ignore
354
/// define_rsa_keypair(<visibility> <prefix>)
355
/// ```
356
///
357
/// This macro creates a struct tuple named `<prefix>Keypair` which contains the lower-level
358
/// cryptographic keypair for an RSA keypair. It derives the deftly RsaKeypair template
359
/// which in turn creates `<prefix>PublicKey` along a series of useful methods.
360
///
361
/// The keypair is NOT clonable by design in order to avoid duplicating secret key material.
362
///
363
/// # Example:
364
///
365
/// ```rust
366
/// use tor_key_forge::define_rsa_keypair;
367
///
368
/// define_rsa_keypair!(NonPublicSigning);
369
/// define_rsa_keypair!(pub PublicSigning);
370
/// define_rsa_keypair!(pub(crate) CratePublicSigning);
371
/// ```
372
///
373
/// The above results in `NonPublicSigningKeypair` and `NonPublicSigningPublicKey` struct being
374
/// created and usable with a series of useful methods. Same for the other defines.
375
///
376
/// You can then use these objects like so:
377
///
378
/// ```rust
379
/// # use tor_llcrypto::rng::FakeEntropicRng;
380
/// # let mut rng = FakeEntropicRng(rand::rng());
381
/// use rand::Rng;
382
/// use tor_key_forge::Keygen;
383
/// use tor_key_forge::define_rsa_keypair;
384
/// use tor_llcrypto::pk::ValidatableSignature;
385
/// use tor_llcrypto::pk::rsa::KeyPair;
386
///
387
/// define_rsa_keypair!(
388
///     /// Our signing key.
389
///     MyRsa
390
/// );
391
///
392
/// let signing_kp = MyRsaKeypair::generate(&mut rng).expect("Invalid keygen");
393
/// let signing_pubkey = signing_kp.public();
394
/// // Lets sign this wonderful message.
395
/// let message = "Workers want rights, not your opinion".as_bytes();
396
/// let sig = signing_kp.sign(&message).expect("Error signing message");
397
///
398
/// // You can then verify either directly with the keypair or the public key.
399
/// assert!(signing_kp.verify(&sig, &message));
400
/// assert!(signing_pubkey.verify(&sig, &message));
401
/// ```
402
#[macro_export]
403
macro_rules! define_rsa_keypair {
404
    ($(#[ $docs_and_attrs:meta ])*
405
     $vis:vis $base_name:ident) => {
406
        $crate::macro_deps::paste! {
407
            #[derive($crate::derive_deftly::Deftly)]
408
            #[derive_deftly($crate::macro_deps::RsaKeypair)]
409
            #[deftly(kp(pubkey = $base_name "PublicKey"))]
410
            #[non_exhaustive]
411
            $(#[ $docs_and_attrs ])*
412
            $vis struct [<$base_name "Keypair">]($crate::macro_deps::rsa::KeyPair);
413
        }
414
    };
415
}
416

            
417
define_derive_deftly! {
418
    /// Implement set of helper functions around a type wrapping a rsa::KeyPair.
419
    export RsaKeypair for struct:
420

            
421
    // Enforce that the object has a single field. We want to avoid the implementer to start
422
    // storing metadata or other things in this object that is meant specifically to be
423
    // a semantic wrapper around an RSA keypair.
424
    ${if not(approx_equal(${for fields { 1 }}, 1)) { ${error "Single field only"}}}
425

            
426
    ${define KP_NAME $( $fname )}
427
    ${define PK_NAME ${tmeta(kp(pubkey)) as ident}}
428

            
429
    /// Public key component of this keypair. Useful if we move the public key around,
430
    /// it then keeps it semantic with the name and less prone to errors.
431
    #[derive(Clone, Debug, PartialEq, Eq)]
432
    #[derive($crate::macro_deps::derive_more::From, $crate::macro_deps::derive_more::Into)]
433
    #[non_exhaustive]
434
    $tvis struct $PK_NAME ($tvis $crate::macro_deps::rsa::PublicKey);
435

            
436
    impl $PK_NAME {
437
        /// Verify the signature of a given message.
438
        #[allow(unused)]
439
        $tvis fn verify(&self, sig: &[u8], text: &[u8]) -> bool {
440
            use $crate::macro_deps::ValidatableSignature;
441
            $crate::macro_deps::rsa::ValidatableRsaSignature::new(&self.0, sig, text).is_valid()
442
        }
443
    }
444

            
445
    // We don't expect all implementations to use all code.
446
    #[allow(unused)]
447
    impl $ttype {
448
        /// Build the raw inner public key into the wrapper public key object.
449
149
        $tvis fn public(&self) -> $PK_NAME {
450
            $PK_NAME((&self.$KP_NAME).into())
451
        }
452

            
453
        /// Reference to the internal keypair.
454
294
        $tvis fn keypair(&self) -> &$crate::macro_deps::rsa::KeyPair {
455
            &self.0
456
        }
457

            
458
        /// Sign the given message.
459
2
        $tvis fn sign(&self, message: &[u8]) -> Result<Vec<u8>, $crate::macro_deps::rsa::Error> {
460
            self.0.sign(message)
461
        }
462

            
463
        /// Verify the signature of a given message.
464
4
        $tvis fn verify(&self, sig: &[u8], text: &[u8]) -> bool {
465
            use $crate::macro_deps::ValidatableSignature;
466
            $crate::macro_deps::rsa::ValidatableRsaSignature::new(
467
                &self.0.to_public_key(), sig, text
468
            ).is_valid()
469
        }
470

            
471
        /// Return a RsaIdentity built from this keypair.
472
        $tvis fn to_rsa_identity(&self) -> $crate::macro_deps::rsa::RsaIdentity {
473
            self.public().0.to_rsa_identity()
474
        }
475
    }
476

            
477
    impl From<$crate::macro_deps::rsa::KeyPair> for $ttype {
478
        fn from(kp: $crate::macro_deps::rsa::KeyPair) -> Self {
479
            Self(kp)
480
        }
481
    }
482

            
483
    /// Implementing EncodableItem, ToEncodableKey and Keygen allows this wrapper key to be stored
484
    /// in a keystore.
485

            
486
    impl $crate::ItemType for $ttype {
487
        fn item_type() -> $crate::KeystoreItemType {
488
            $crate::KeyType::RsaKeypair.into()
489
        }
490
    }
491

            
492
    impl $crate::EncodableItem for $ttype {
493
        fn as_keystore_item(&self) -> $crate::Result<$crate::KeystoreItem> {
494
            self.$KP_NAME.as_keystore_item()
495
        }
496
    }
497

            
498
    impl $crate::ToEncodableKey for $ttype {
499
        type Key = $crate::macro_deps::rsa::KeyPair;
500
        type KeyPair = $ttype;
501

            
502
        fn to_encodable_key(self) -> Self::Key {
503
            self.$KP_NAME
504
        }
505
686
        fn from_encodable_key(key: Self::Key) -> Self {
506
            Self(key)
507
        }
508
    }
509

            
510
    impl $crate::Keygen for $ttype {
511
51
        fn generate(mut rng: &mut dyn $crate::KeygenRng) -> $crate::Result<Self>
512
51
        where
513
51
            Self: Sized
514
        {
515
            Ok(Self { $KP_NAME: $crate::macro_deps::rsa::KeyPair::generate(&mut rng)? })
516
        }
517
    }
518
}
519

            
520
// Re-export dependencies as `tor_key_forge::macro_deps` that we use to make this macro work.
521
#[doc(hidden)]
522
pub mod deps {
523
    pub use derive_deftly_template_Curve25519Keypair;
524
    pub use derive_deftly_template_Ed25519Keypair;
525
    pub use derive_deftly_template_RsaKeypair;
526
    pub use derive_more;
527
    pub use paste::paste;
528
    pub use signature;
529
    pub use tor_llcrypto::pk::{ValidatableSignature, curve25519, ed25519, rsa};
530
}
531

            
532
#[cfg(test)]
533
mod test {
534
    use crate::Keygen;
535
    use tor_basic_utils::test_rng::testing_rng;
536
    use tor_llcrypto::{pk::ed25519::Ed25519SigningKey, rng::FakeEntropicRng};
537

            
538
    #[test]
539
    fn deftly_ed25519_keypair() {
540
        define_ed25519_keypair!(SomeEd25519);
541

            
542
        let mut rng = FakeEntropicRng(testing_rng());
543
        let kp = SomeEd25519Keypair::generate(&mut rng).expect("Failed to gen key");
544

            
545
        // Make sure the generated public key from our wrapper is the same as the
546
        // underlying keypair.
547
        let pubkey = kp.public();
548
        assert_eq!(pubkey.0, kp.0.verifying_key());
549

            
550
        // Message to sign and verify.
551
        let msg: [u8; 4] = [2, 3, 4, 5];
552
        let msg_bad: [u8; 4] = [2, 3, 4, 6];
553

            
554
        let sig = kp.sign(msg.as_slice());
555
        assert!(kp.verify(sig, msg.as_slice()));
556
        // Lets make sure we don't validate another message.
557
        assert!(!kp.verify(sig, msg_bad.as_slice()));
558
    }
559

            
560
    #[test]
561
    fn deftly_rsa_keypair() {
562
        define_rsa_keypair!(SomeRsa);
563

            
564
        let mut rng = FakeEntropicRng(testing_rng());
565
        let kp = SomeRsaKeypair::generate(&mut rng).expect("Failed to gen key");
566

            
567
        // Make sure the generated public key from our wrapper is the same as the
568
        // underlying keypair.
569
        let pubkey = kp.public();
570
        assert_eq!(pubkey.0, kp.0.to_public_key());
571

            
572
        // Message to sign and verify.
573
        let msg: [u8; 4] = [2, 3, 4, 5];
574
        let msg_bad: [u8; 4] = [2, 3, 4, 6];
575

            
576
        let sig = kp.sign(msg.as_slice()).expect("Failed to sign message.");
577
        assert!(kp.verify(&sig, msg.as_slice()));
578
        // Lets make sure we don't validate another message.
579
        assert!(!kp.verify(&sig, msg_bad.as_slice()));
580
    }
581
}