xrpl/core/keypairs/
algorithms.rs

1//! Ed25519 elliptic curve cryptography interface.
2//! SECP256K1 elliptic curve cryptography interface.
3//!
4//! Note: The process for using SECP256k1 is complex and
5//! more involved than ED25519.
6//!
7//! See SECP256K1 Key Derivation:
8//! `<https://xrpl.org/cryptographic-keys.html#secp256k1-key-derivation>`
9
10use crate::constants::CryptoAlgorithm;
11use crate::core::exceptions::XRPLCoreResult;
12use crate::core::keypairs::exceptions::XRPLKeypairsException;
13use crate::core::keypairs::utils::*;
14use crate::core::keypairs::CryptoImplementation;
15use alloc::format;
16use alloc::string::String;
17use alloc::vec::Vec;
18use core::convert::TryInto;
19use core::str::FromStr;
20use crypto_bigint::Encoding;
21use crypto_bigint::U256;
22use ed25519_dalek::ed25519::signature::SignerMut;
23use ed25519_dalek::Verifier;
24use ed25519_dalek::SECRET_KEY_LENGTH;
25use secp256k1::ecdsa;
26use secp256k1::Scalar;
27
28/// Methods for using the ECDSA cryptographic system with
29/// the SECP256K1 elliptic curve.
30pub struct Secp256k1;
31
32/// Methods for using the ED25519 cryptographic system.
33pub struct Ed25519;
34
35impl Secp256k1 {
36    /// Hex encode the private key.
37    fn _private_key_to_str(key: secp256k1::SecretKey) -> String {
38        hex::encode_upper(key.as_ref())
39    }
40
41    /// Hex encode the public key.
42    fn _public_key_to_str(key: secp256k1::PublicKey) -> String {
43        hex::encode_upper(key.serialize())
44    }
45
46    /// Format a provided key.
47    fn _format_key(keystr: &str) -> String {
48        format!("{keystr:0>SECP256K1_KEY_LENGTH$}")
49    }
50
51    /// Format the public and private keys.
52    /// TODO Make function constant time
53    fn _format_keys(
54        public: secp256k1::PublicKey,
55        private: secp256k1::SecretKey,
56    ) -> (String, String) {
57        (
58            Secp256k1::_format_key(&Secp256k1::_public_key_to_str(public)),
59            Secp256k1::_format_key(&Secp256k1::_private_key_to_str(private)),
60        )
61    }
62
63    /// Hash the message to prevent insecure signing.
64    fn _get_message(message: &[u8]) -> secp256k1::Message {
65        secp256k1::Message::from_digest(sha512_first_half(message))
66    }
67
68    /// Determing if the provided secret key is valid.
69    /// TODO Make function constant time
70    fn _is_secret_valid(key: [u8; u32::BITS as usize]) -> bool {
71        let key_bytes = U256::from_be_bytes(key);
72        key_bytes >= U256::ONE
73            && key_bytes <= U256::from_be_bytes(secp256k1::constants::CURVE_ORDER)
74    }
75
76    /// Concat candidate key.
77    fn _candidate_merger(input: &[u8], candidate: &[u8], phase: &Secp256k1Phase) -> Vec<u8> {
78        if phase == &Secp256k1Phase::Root {
79            [input, candidate].concat()
80        } else {
81            [input, &SECP256K1_INTERMEDIATE_KEYPAIR_PADDING, candidate].concat()
82        }
83    }
84
85    /// Given bytes_input determine public/private keypair
86    /// for a given phase of this algorithm. The difference
87    /// between generating the root and intermediate keypairs
88    /// is just what bytes are input by the caller and that
89    /// the intermediate keypair needs to inject
90    /// SECP256K1_INTERMEDIATE_KEYPAIR_PADDING into the value
91    /// to hash to get the raw private key.
92    fn _derive_part(
93        bytes: &[u8],
94        phase: Secp256k1Phase,
95    ) -> XRPLCoreResult<(secp256k1::PublicKey, secp256k1::SecretKey)> {
96        let raw_private = Self::_get_secret(bytes, &phase)?;
97        let secp = secp256k1::Secp256k1::new();
98        let wrapped_private = secp256k1::SecretKey::from_slice(&raw_private)
99            .map_err(XRPLKeypairsException::SECP256K1Error)?;
100        let wrapped_public = secp256k1::PublicKey::from_secret_key(&secp, &wrapped_private);
101
102        Ok((wrapped_public, wrapped_private))
103    }
104
105    /// Derive the final public/private keys.
106    fn _derive_final(
107        root_public: secp256k1::PublicKey,
108        root_private: secp256k1::SecretKey,
109        mid_public: secp256k1::PublicKey,
110        mid_private: secp256k1::SecretKey,
111    ) -> XRPLCoreResult<(secp256k1::PublicKey, secp256k1::SecretKey)> {
112        let wrapped_private = root_private
113            .add_tweak(&Scalar::from(mid_private))
114            .map_err(XRPLKeypairsException::SECP256K1Error)?;
115        let wrapped_public = root_public
116            .combine(&mid_public)
117            .map_err(XRPLKeypairsException::SECP256K1Error)?;
118
119        Ok((wrapped_public, wrapped_private))
120    }
121
122    /// Given a function `candidate_merger` that knows how
123    /// to prepare a sequence candidate bytestring into a
124    /// possible full candidate secret, returns the first
125    /// sequence value that is valid. If none are valid,
126    /// raises; however this should be so exceedingly rare
127    /// as to ignore.
128    fn _get_secret(
129        input: &[u8],
130        phase: &Secp256k1Phase,
131    ) -> XRPLCoreResult<[u8; SHA512_HASH_LENGTH]> {
132        for raw_root in 0..SECP256K1_SEQUENCE_MAX {
133            let root = (raw_root as u32).to_be_bytes();
134            let candidate = sha512_first_half(&Self::_candidate_merger(input, &root, phase));
135
136            if Self::_is_secret_valid(candidate) {
137                return Ok(candidate);
138            } else {
139                continue;
140            }
141        }
142
143        Err(XRPLKeypairsException::InvalidSecret.into())
144    }
145}
146
147impl Ed25519 {
148    /// Hex encode the private key.
149    fn _private_key_to_str(key: ed25519_dalek::SecretKey) -> String {
150        hex::encode(key)
151    }
152
153    /// Hex encode the public key.
154    fn _public_key_to_str(key: ed25519_dalek::VerifyingKey) -> String {
155        hex::encode(key.as_ref())
156    }
157
158    /// Format a provided key.
159    /// TODO Determine security implications
160    fn _format_key(keystr: &str) -> String {
161        format!("{}{}", ED25519_PREFIX, keystr.to_uppercase())
162    }
163
164    /// Format the public and private keys.
165    fn _format_keys(
166        public: ed25519_dalek::VerifyingKey,
167        private: ed25519_dalek::SecretKey,
168    ) -> (String, String) {
169        (
170            Ed25519::_format_key(&Ed25519::_public_key_to_str(public)),
171            Ed25519::_format_key(&Ed25519::_private_key_to_str(private)),
172        )
173    }
174}
175
176impl CryptoImplementation for Secp256k1 {
177    /// Derives a key pair for use with the XRP Ledger
178    /// from a seed value.
179    ///
180    /// # Examples
181    ///
182    /// ## Basic usage
183    ///
184    /// ```
185    /// use xrpl::core::keypairs::Secp256k1;
186    /// use xrpl::core::keypairs::exceptions::XRPLKeypairsException;
187    /// use xrpl::core::keypairs::CryptoImplementation;
188    /// use xrpl::core::exceptions::XRPLCoreException;
189    ///
190    /// let decoded_seed: &[u8] = &[
191    ///     207, 45, 227, 120, 251, 221, 126, 46,
192    ///     232, 125, 72, 109, 251, 90, 123, 255
193    /// ];
194    /// let validator: bool = false;
195    /// let tuple: (String, String) = (
196    ///     "0203F2D90BC50012EC7CB20B07A1B818D6863636FB1E945D17449092CFB5495E1E".into(),
197    ///     "0048D93A3B5948E5F9B323BF654BFAD6E8FF75B5FCAB03C5A55AD30CB2515B461F".into(),
198    /// );
199    ///
200    /// let derivation: Option<(String, String)> = match Secp256k1.derive_keypair(
201    ///     decoded_seed,
202    ///     validator,
203    /// ) {
204    ///     Ok((public, private)) => Some((public, private)),
205    ///     Err(e) => match e {
206    ///         XRPLCoreException::XRPLKeypairsError(XRPLKeypairsException::InvalidSignature) => None,
207    ///         XRPLCoreException::XRPLKeypairsError(XRPLKeypairsException::InvalidSecret) => None,
208    ///         XRPLCoreException::XRPLKeypairsError(XRPLKeypairsException::SECP256K1Error(_)) => None,
209    ///         _ => None,
210    ///     },
211    /// };
212    ///
213    /// assert_eq!(Some(tuple), derivation);
214    /// ```
215    fn derive_keypair(
216        &self,
217        decoded_seed: &[u8],
218        is_validator: bool,
219    ) -> XRPLCoreResult<(String, String)> {
220        let (root_public, root_secret) = Self::_derive_part(decoded_seed, Secp256k1Phase::Root)?;
221        if is_validator {
222            Ok(Secp256k1::_format_keys(root_public, root_secret))
223        } else {
224            let (mid_public, mid_secret) =
225                Self::_derive_part(&root_public.serialize(), Secp256k1Phase::Mid)?;
226            let (final_public, final_secret) =
227                Self::_derive_final(root_public, root_secret, mid_public, mid_secret)?;
228
229            Ok(Secp256k1::_format_keys(final_public, final_secret))
230        }
231    }
232
233    /// Signs a message using a given private key.
234    /// * `message` - Text about foo.
235    /// * `private_key` - Text about bar.
236    ///
237    /// # Examples
238    ///
239    /// ## Basic usage
240    ///
241    /// ```
242    /// use xrpl::core::keypairs::Secp256k1;
243    /// use xrpl::core::keypairs::exceptions::XRPLKeypairsException;
244    /// use xrpl::core::keypairs::CryptoImplementation;
245    /// use xrpl::core::exceptions::XRPLCoreException;
246    ///
247    /// let message: &[u8] = "test message".as_bytes();
248    /// let private_key: &str = "00D78B9735C3F26501C7337B8A5727FD5\
249    ///                          3A6EFDBC6AA55984F098488561F985E23";
250    /// let signature: Vec<u8> = vec![
251    ///     48, 68, 2, 32, 88, 58, 145, 201, 94, 84, 230, 166, 81, 196,
252    ///     123, 236, 34, 116, 78, 11, 16, 30, 44, 64, 96, 231, 176, 143,
253    ///     99, 65, 101, 125, 173, 155, 195, 238, 2, 32, 125, 20, 137,
254    ///     199, 57, 93, 176, 24, 141, 58, 86, 169, 119, 236, 186, 84,
255    ///     179, 111, 169, 55, 27, 64, 49, 150, 85, 177, 180, 66, 158,
256    ///     51, 239, 45,
257    /// ];
258    ///
259    /// let signing: Option<Vec<u8>> = match Secp256k1.sign(
260    ///     message,
261    ///     private_key,
262    /// ) {
263    ///     Ok(signature) => Some(signature),
264    ///     Err(e) => match e {
265    ///         XRPLCoreException::XRPLKeypairsError(XRPLKeypairsException::SECP256K1Error(_)) => None,
266    ///         _ => None,
267    ///     },
268    /// };
269    ///
270    /// assert_eq!(Some(signature), signing);
271    /// ```
272    fn sign(&self, message_bytes: &[u8], private_key: &str) -> XRPLCoreResult<Vec<u8>> {
273        let secp = secp256k1::Secp256k1::<secp256k1::SignOnly>::signing_only();
274        let message = Self::_get_message(message_bytes);
275        let trimmed_key = private_key.trim_start_matches(SECP256K1_PREFIX);
276        let private = secp256k1::SecretKey::from_str(trimmed_key)
277            .map_err(XRPLKeypairsException::SECP256K1Error)?;
278        let signature = secp.sign_ecdsa(&message, &private);
279
280        Ok(signature.serialize_der().to_vec())
281    }
282
283    /// Verifies the signature on a given message.
284    ///
285    /// # Examples
286    ///
287    /// ## Basic usage
288    ///
289    /// ```
290    /// use xrpl::core::keypairs::Secp256k1;
291    /// use xrpl::core::keypairs::exceptions::XRPLKeypairsException;
292    /// use xrpl::core::keypairs::CryptoImplementation;
293    ///
294    /// let message: &[u8] = "test message".as_bytes();
295    /// let signature: &str = "30440220583A91C95E54E6A651C47BEC\
296    ///                        22744E0B101E2C4060E7B08F6341657D\
297    ///                        AD9BC3EE02207D1489C7395DB0188D3A\
298    ///                        56A977ECBA54B36FA9371B40319655B1\
299    ///                        B4429E33EF2D";
300    /// let public_key: &str = "030D58EB48B4420B1F7B9DF55087E0E\
301    ///                         29FEF0E8468F9A6825B01CA2C361042D435";
302    ///
303    /// assert!(Secp256k1.is_valid_message(
304    ///     message,
305    ///     signature,
306    ///     public_key,
307    /// ));
308    /// ```
309    fn is_valid_message(&self, message_bytes: &[u8], signature: &str, public_key: &str) -> bool {
310        let secp = secp256k1::Secp256k1::<secp256k1::VerifyOnly>::verification_only();
311        let msg = Self::_get_message(message_bytes);
312
313        if let Ok(value) = hex::decode(signature) {
314            let sig = ecdsa::Signature::from_der(&value);
315            let public = secp256k1::PublicKey::from_str(public_key);
316
317            if let (&Ok(s), &Ok(p)) = (&sig.as_ref(), &public.as_ref()) {
318                secp.verify_ecdsa(&msg, s, p).is_ok()
319            } else {
320                false
321            }
322        } else {
323            false
324        }
325    }
326}
327
328impl CryptoImplementation for Ed25519 {
329    /// Derives a key pair for use with the XRP Ledger
330    /// from a seed value.
331    ///
332    /// # Examples
333    ///
334    /// ## Basic usage
335    ///
336    /// ```
337    /// use xrpl::core::keypairs::Ed25519;
338    /// use xrpl::core::keypairs::exceptions::XRPLKeypairsException;
339    /// use xrpl::core::keypairs::CryptoImplementation;
340    /// use xrpl::core::exceptions::XRPLCoreException;
341    ///
342    /// let decoded_seed: &[u8] = &[
343    ///     207, 45, 227, 120, 251, 221, 126, 46,
344    ///     232, 125, 72, 109, 251, 90, 123, 255
345    /// ];
346    /// let validator: bool = false;
347    /// let tuple: (String, String) = (
348    ///     "ED60292139838CB86E719134F848F055057CA5BDA61F5A529729F1697502D53E1C".into(),
349    ///     "ED009F66528611A0D400946A01FA01F8AF4FF4C1D0C744AE3F193317DCA77598F1".into(),
350    /// );
351    ///
352    /// let derivation: Option<(String, String)> = match Ed25519.derive_keypair(
353    ///     decoded_seed,
354    ///     validator,
355    /// ) {
356    ///     Ok((public, private)) => Some((public, private)),
357    ///     Err(e) => match e {
358    ///         XRPLCoreException::XRPLKeypairsError(XRPLKeypairsException::InvalidSignature) => None,
359    ///         XRPLCoreException::XRPLKeypairsError(XRPLKeypairsException::ED25519Error) => None,
360    ///         XRPLCoreException::XRPLKeypairsError(XRPLKeypairsException::UnsupportedValidatorAlgorithm { expected: _ }) => None,
361    ///         _ => None,
362    ///     },
363    /// };
364    ///
365    /// assert_eq!(Some(tuple), derivation);
366    /// ```
367    fn derive_keypair(
368        &self,
369        decoded_seed: &[u8],
370        is_validator: bool,
371    ) -> XRPLCoreResult<(String, String)> {
372        if is_validator {
373            Err(XRPLKeypairsException::UnsupportedValidatorAlgorithm {
374                expected: CryptoAlgorithm::ED25519,
375            }
376            .into())
377        } else {
378            let raw_private = sha512_first_half(decoded_seed);
379            let private: [u8; SECRET_KEY_LENGTH] = ed25519_dalek::SecretKey::from(raw_private);
380            let signing_key: ed25519_dalek::SigningKey = private.into();
381            let public = (&signing_key).into();
382
383            Ok(Ed25519::_format_keys(public, private))
384        }
385    }
386
387    /// Signs a message using a given private key.
388    /// * `message` - Text about foo.
389    /// * `private_key` - Text about bar.
390    ///
391    /// # Examples
392    ///
393    /// ## Basic usage
394    ///
395    /// ```
396    /// use xrpl::core::keypairs::Ed25519;
397    /// use xrpl::core::keypairs::exceptions::XRPLKeypairsException;
398    /// use xrpl::core::keypairs::CryptoImplementation;
399    ///
400    /// let message: &[u8] = "test message".as_bytes();
401    /// let private_key: &str = "EDB4C4E046826BD26190D09715FC31F4E\
402    ///                          6A728204EADD112905B08B14B7F15C4F3";
403    /// let signature: Vec<u8> = vec![
404    ///     203, 25, 158, 27, 253, 78, 61, 170, 16, 94, 72, 50, 238, 223,
405    ///     163, 100, 19, 225, 244, 66, 5,228, 239, 185, 226, 126, 130, 96,
406    ///     68, 194, 30, 62, 46, 132, 139, 188, 129, 149, 232, 149, 155,
407    ///     173, 248, 135, 89, 155, 115, 16, 173, 27, 112, 71, 239, 17,
408    ///     182, 130, 224, 208, 104, 247, 55,73, 117, 14,
409    /// ];
410    ///
411    /// let signing: Option<Vec<u8>> = Some(Ed25519.sign(
412    ///     message,
413    ///     private_key,
414    /// ).unwrap());
415    ///
416    /// assert_eq!(Some(signature), signing);
417    /// ```
418    fn sign(&self, message: &[u8], private_key: &str) -> XRPLCoreResult<Vec<u8>> {
419        let raw_private = hex::decode(&private_key[ED25519_PREFIX.len()..])?;
420        let raw_private_slice: &[u8; SECRET_KEY_LENGTH] = raw_private
421            .as_slice()
422            .try_into()
423            .map_err(|_| XRPLKeypairsException::InvalidSecret)?;
424        let private: ed25519_dalek::SecretKey = *raw_private_slice;
425        let mut signing_key: ed25519_dalek::SigningKey = private.into();
426        let signature = signing_key.sign(message);
427
428        Ok(signature.to_bytes().to_vec())
429    }
430
431    /// Verifies the signature on a given message.
432    ///
433    /// # Examples
434    ///
435    /// ## Basic usage
436    ///
437    /// ```
438    /// use xrpl::core::keypairs::Ed25519;
439    /// use xrpl::core::keypairs::exceptions::XRPLKeypairsException;
440    /// use xrpl::core::keypairs::CryptoImplementation;
441    ///
442    /// let message: &[u8] = "test message".as_bytes();
443    /// let signature: &str = "CB199E1BFD4E3DAA105E4832EEDFA3641\
444    ///                        3E1F44205E4EFB9E27E826044C21E3E2E\
445    ///                        848BBC8195E8959BADF887599B7310AD1\
446    ///                        B7047EF11B682E0D068F73749750E";
447    /// let public_key: &str = "ED01FA53FA5A7E77798F882ECE20B1AB\
448    ///                         C00BB358A9E55A202D0D0676BD0CE37A63";
449    ///
450    /// assert!(Ed25519.is_valid_message(
451    ///     message,
452    ///     signature,
453    ///     public_key,
454    /// ));
455    /// ```
456    fn is_valid_message(&self, message: &[u8], signature: &str, public_key: &str) -> bool {
457        let raw_public = hex::decode(&public_key[ED25519_PREFIX.len()..]);
458        let decoded_sig = hex::decode(signature);
459
460        if raw_public.is_err() || decoded_sig.is_err() {
461            return false;
462        };
463
464        if let (Ok(rpub), Ok(dsig)) = (raw_public, decoded_sig) {
465            let rpub = rpub.as_slice().try_into().unwrap();
466            let public = ed25519_dalek::VerifyingKey::from_bytes(rpub);
467
468            if dsig.len() != ED25519_SIGNATURE_LENGTH {
469                return false;
470            };
471
472            if let Ok(value) = public {
473                let sig: [u8; ED25519_SIGNATURE_LENGTH] =
474                    dsig.try_into().expect("is_valid_message");
475                let converted = &ed25519_dalek::Signature::from(sig);
476
477                value.verify(message, converted).is_ok()
478            } else {
479                false
480            }
481        } else {
482            false
483        }
484    }
485}
486
487#[cfg(test)]
488mod test {
489    use super::*;
490    use crate::core::keypairs::test_cases::*;
491
492    #[test]
493    fn test_secp256k1_derive_keypair() {
494        let seed: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
495        let validator = Secp256k1.derive_keypair(seed, true);
496        let (public, private) = Secp256k1.derive_keypair(seed, false).unwrap();
497
498        assert!(validator.is_ok());
499        assert_eq!(PRIVATE_SECP256K1, private);
500        assert_eq!(PUBLIC_SECP256K1, public);
501    }
502
503    #[test]
504    fn test_secp256k1_sign() {
505        let success = Secp256k1.sign(TEST_MESSAGE.as_bytes(), PRIVATE_SECP256K1);
506        let error = Secp256k1.sign(TEST_MESSAGE.as_bytes(), "abc123");
507
508        assert!(success.is_ok());
509        assert!(error.is_err());
510    }
511
512    #[test]
513    fn test_secp256k1_is_valid_message() {
514        let signature: &str = &hex::encode_upper(SIGNATURE_SECP256K1);
515        let message: &[u8] = TEST_MESSAGE.as_bytes();
516
517        assert!(Secp256k1.is_valid_message(message, signature, PUBLIC_SECP256K1));
518    }
519
520    #[test]
521    fn test_ed25519_derive_keypair() {
522        let seed: &[u8] = SEED_ED25519.as_bytes();
523        let validator = Ed25519.derive_keypair(seed, true);
524        let (public, private) = Ed25519.derive_keypair(seed, false).unwrap();
525
526        assert!(validator.is_err());
527        assert_eq!(RAW_PRIVATE_ED25519, public);
528        assert_eq!(RAW_PUBLIC_ED25519, private);
529    }
530
531    #[test]
532    fn test_ed25519_sign() {
533        let success = Ed25519.sign(TEST_MESSAGE.as_bytes(), RAW_PRIVATE_ED25519);
534        let error = Ed25519.sign(TEST_MESSAGE.as_bytes(), "abc123");
535
536        assert!(success.is_ok());
537        assert!(error.is_err());
538    }
539
540    #[test]
541    fn test_ed25519_is_valid_message() {
542        let signature: &str = &hex::encode_upper(SIGNATURE_ED25519);
543        let message: &[u8] = TEST_MESSAGE.as_bytes();
544
545        assert!(Ed25519.is_valid_message(message, signature, PUBLIC_ED25519));
546    }
547}