Skip to main content

xrpl_common_stdlib/types/
public_key.rs

1pub const PUBLIC_KEY_BUFFER_SIZE: usize = 33;
2
3/// A 33-byte public key for secp256k1 and ed25519 DSA types.
4///
5/// Public keys on the XRP Ledger are 33 bytes and can be either:
6/// - **secp256k1**: Compressed ECDSA public key (0x02 or 0x03 prefix)
7/// - **ed25519**: EdDSA public key (0xED prefix)
8///
9/// ## Derived Traits
10///
11/// - `PartialEq, Eq`: Enable comparisons and use in collections
12/// - `Debug, Clone`: Standard traits for development and consistency
13///
14/// Note: `Copy` is intentionally not derived due to the struct's size (33 bytes).
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct PublicKey(pub [u8; PUBLIC_KEY_BUFFER_SIZE]);
17
18impl From<[u8; PUBLIC_KEY_BUFFER_SIZE]> for PublicKey {
19    fn from(bytes: [u8; PUBLIC_KEY_BUFFER_SIZE]) -> Self {
20        Self(bytes) // Access private field legally here
21    }
22}
23
24impl From<[u8; 64]> for PublicKey {
25    fn from(bytes: [u8; 64]) -> Self {
26        // Take the first PUBLIC_KEY_BUFFER_SIZE bytes from the 64-byte array
27        let mut key_bytes = [0u8; PUBLIC_KEY_BUFFER_SIZE];
28        key_bytes.copy_from_slice(&bytes[..PUBLIC_KEY_BUFFER_SIZE]);
29        PublicKey(key_bytes)
30    }
31}
32
33impl From<&[u8]> for PublicKey {
34    fn from(bytes: &[u8]) -> Self {
35        let mut key_bytes = [0u8; PUBLIC_KEY_BUFFER_SIZE];
36        key_bytes[..bytes.len().min(PUBLIC_KEY_BUFFER_SIZE)]
37            .copy_from_slice(&bytes[..bytes.len().min(PUBLIC_KEY_BUFFER_SIZE)]);
38        PublicKey(key_bytes)
39    }
40}
41
42#[cfg(test)]
43mod test_public_key {
44    use crate::types::public_key::PUBLIC_KEY_BUFFER_SIZE;
45
46    // secp256k1
47    const PUBKEY_SECP256K1: [u8; PUBLIC_KEY_BUFFER_SIZE] = [
48        0x02, 0xC7, 0x38, 0x7F, 0xFC, 0x25, 0xC1, 0x56, 0xCA, 0x7F, 0x8A, 0x6D, 0x76, 0x0C, 0x8D,
49        0x01, 0xEF, 0x64, 0x2C, 0xEE, 0x9C, 0xE4, 0x68, 0x0C, 0x33, 0xFF, 0xB3, 0xFF, 0x39, 0xAF,
50        0xEC, 0xFE, 0x70,
51    ];
52
53    // ed25519
54    const PUBKEY_ED25519: [u8; PUBLIC_KEY_BUFFER_SIZE] = [
55        0xED, 0xD9, 0xB3, 0x59, 0x98, 0x02, 0xB2, 0x14, 0xA9, 0x9D, 0x75, 0x77, 0x12, 0xD6, 0xAB,
56        0xDF, 0x72, 0xF8, 0x3C, 0x63, 0xBB, 0xD5, 0x38, 0x61, 0x41, 0x17, 0x90, 0xB1, 0x3D, 0x04,
57        0xB2, 0xC5, 0xC9,
58    ];
59
60    // uint8_t sig_ed[] =
61    // {
62    // 0x56,0x68,0x80,0x76,0x70,0xFE,0xCE,0x60,0x34,0xAF,
63    // 0xD6,0xCD,0x1B,0xB4,0xC6,0x60,0xAE,0x08,0x39,0x6D,
64    // 0x6D,0x8B,0x7D,0x22,0x71,0x3B,0xDA,0x26,0x43,0xC1,
65    // 0xE1,0x91,0xC4,0xE4,0x4D,0x8E,0x02,0xE8,0x57,0x8B,
66    // 0x20,0x45,0xDA,0xD4,0x8F,0x97,0xFC,0x16,0xF8,0x92,
67    // 0x5B,0x6B,0x51,0xFB,0x3B,0xE5,0x0F,0xB0,0x4B,0x3A,
68    // 0x20,0x4C,0x53,0x04U
69    // };
70
71    #[test]
72    fn test_get_ref() {
73        let pubkey_secp256k1_ref: &[u8] = PUBKEY_SECP256K1.as_slice();
74
75        assert_eq!(pubkey_secp256k1_ref.len(), PUBLIC_KEY_BUFFER_SIZE);
76        assert_eq!(pubkey_secp256k1_ref, PUBKEY_SECP256K1);
77        assert_ne!(pubkey_secp256k1_ref, PUBKEY_ED25519);
78    }
79
80    #[test]
81    fn test_from_33_bytes() {
82        use super::PublicKey;
83        let pk = PublicKey::from(PUBKEY_SECP256K1);
84        assert_eq!(pk.0, PUBKEY_SECP256K1);
85    }
86
87    #[test]
88    fn test_from_64_bytes_truncates() {
89        use super::PublicKey;
90        let mut bytes_64 = [0xAA; 64];
91        bytes_64[0] = 0x02; // secp256k1 prefix
92        let pk = PublicKey::from(bytes_64);
93        assert_eq!(pk.0, bytes_64[..PUBLIC_KEY_BUFFER_SIZE]);
94    }
95
96    #[test]
97    fn test_from_slice_exact_size() {
98        use super::PublicKey;
99        let slice: &[u8] = &PUBKEY_ED25519;
100        let pk = PublicKey::from(slice);
101        assert_eq!(pk.0, PUBKEY_ED25519);
102    }
103
104    #[test]
105    fn test_from_slice_shorter_pads_with_zeros() {
106        use super::PublicKey;
107        let short: &[u8] = &[0xED, 0x01, 0x02];
108        let pk = PublicKey::from(short);
109        assert_eq!(&pk.0[..3], short);
110        assert_eq!(&pk.0[3..], &[0u8; PUBLIC_KEY_BUFFER_SIZE - 3]);
111    }
112
113    #[test]
114    fn test_from_slice_longer_truncates() {
115        use super::PublicKey;
116        let long: Vec<u8> = (0..64).collect();
117        let pk = PublicKey::from(long.as_slice());
118        assert_eq!(&pk.0, &long[..PUBLIC_KEY_BUFFER_SIZE]);
119    }
120
121    #[test]
122    fn test_from_slice_empty() {
123        use super::PublicKey;
124        let empty: &[u8] = &[];
125        let pk = PublicKey::from(empty);
126        assert_eq!(pk.0, [0u8; PUBLIC_KEY_BUFFER_SIZE]);
127    }
128}