dpp/identity/identity_public_key/v0/methods/
mod.rs1use crate::identity::identity_public_key::methods::hash::IdentityPublicKeyHashMethodsV0;
2use crate::identity::identity_public_key::v0::IdentityPublicKeyV0;
3use crate::identity::KeyType;
4use crate::util::hash::ripemd160_sha256;
5use crate::ProtocolError;
6use anyhow::anyhow;
7#[cfg(feature = "ed25519-dalek")]
8use dashcore::ed25519_dalek;
9use dashcore::hashes::Hash;
10use dashcore::key::Secp256k1;
11use dashcore::secp256k1::SecretKey;
12use dashcore::{Network, PublicKey as ECDSAPublicKey};
13use platform_value::Bytes20;
14#[cfg(feature = "bls-signatures")]
15use {crate::bls_signatures, dashcore::blsful::Bls12381G2Impl};
16impl IdentityPublicKeyHashMethodsV0 for IdentityPublicKeyV0 {
17 fn public_key_hash(&self) -> Result<[u8; 20], ProtocolError> {
19 if self.data.is_empty() {
20 return Err(ProtocolError::EmptyPublicKeyDataError);
21 }
22
23 match self.key_type {
24 KeyType::ECDSA_SECP256K1 => {
25 let key = match self.data.len() {
26 65 | 33 => ECDSAPublicKey::from_slice(self.data.as_slice())
28 .map_err(|e| anyhow!("unable to create pub key - {}", e))?,
29 _ => {
30 return Err(ProtocolError::ParsingError(format!(
31 "the key length is invalid: {} Allowed sizes: 33 or 65 bytes for ecdsa key",
32 self.data.len()
33 )));
34 }
35 };
36 Ok(key.pubkey_hash().to_byte_array())
37 }
38 KeyType::BLS12_381 => {
39 if self.data.len() != 48 {
40 Err(ProtocolError::ParsingError(format!(
41 "the key length is invalid: {} Allowed sizes: 48 bytes for bls key",
42 self.data.len()
43 )))
44 } else {
45 Ok(ripemd160_sha256(self.data.as_slice()))
46 }
47 }
48 KeyType::ECDSA_HASH160 | KeyType::BIP13_SCRIPT_HASH | KeyType::EDDSA_25519_HASH160 => {
49 Ok(Bytes20::from_vec(self.data.to_vec())?.into_buffer())
50 }
51 }
52 }
53
54 fn validate_private_key_bytes(
55 &self,
56 private_key_bytes: &[u8; 32],
57 network: Network,
58 ) -> Result<bool, ProtocolError> {
59 match self.key_type {
60 KeyType::ECDSA_SECP256K1 => {
61 let secp = Secp256k1::new();
62 let secret_key = match SecretKey::from_byte_array(private_key_bytes) {
63 Ok(secret_key) => secret_key,
64 Err(_) => return Ok(false),
65 };
66 let private_key = dashcore::PrivateKey::new(secret_key, network);
67
68 Ok(private_key.public_key(&secp).to_bytes() == self.data.as_slice())
69 }
70 KeyType::BLS12_381 => {
71 #[cfg(feature = "bls-signatures")]
72 {
73 let private_key: Option<bls_signatures::SecretKey<Bls12381G2Impl>> =
74 bls_signatures::SecretKey::<Bls12381G2Impl>::from_be_bytes(
75 private_key_bytes,
76 )
77 .into();
78 if private_key.is_none() {
79 return Ok(false);
80 }
81 let private_key = private_key.expect("expected private key");
82
83 Ok(private_key.public_key().0.to_compressed() == self.data.as_slice())
84 }
85 #[cfg(not(feature = "bls-signatures"))]
86 return Err(ProtocolError::NotSupported(
87 "Converting a private key to a bls public key is not supported without the bls-signatures feature".to_string(),
88 ));
89 }
90 KeyType::ECDSA_HASH160 => {
91 let secp = Secp256k1::new();
92 let secret_key = match SecretKey::from_byte_array(private_key_bytes) {
93 Ok(secret_key) => secret_key,
94 Err(_) => return Ok(false),
95 };
96 let private_key = dashcore::PrivateKey::new(secret_key, network);
97
98 Ok(
99 ripemd160_sha256(private_key.public_key(&secp).to_bytes().as_slice())
100 .as_slice()
101 == self.data.as_slice(),
102 )
103 }
104 KeyType::EDDSA_25519_HASH160 => {
105 #[cfg(feature = "ed25519-dalek")]
106 {
107 let key_pair = ed25519_dalek::SigningKey::from_bytes(private_key_bytes);
108 Ok(
109 ripemd160_sha256(key_pair.verifying_key().to_bytes().as_slice()).as_slice()
110 == self.data.as_slice(),
111 )
112 }
113 #[cfg(not(feature = "ed25519-dalek"))]
114 return Err(ProtocolError::NotSupported(
115 "Converting a private key to a eddsa hash 160 is not supported without the ed25519-dalek feature".to_string(),
116 ));
117 }
118 KeyType::BIP13_SCRIPT_HASH => Err(ProtocolError::NotSupported(
119 "Converting a private key to a script hash is not supported".to_string(),
120 )),
121 }
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128 use crate::identity::{Purpose, SecurityLevel};
129 use dashcore::blsful::{Bls12381G2Impl, Pairing, Signature, SignatureSchemes};
130 use dashcore::Network;
131 use dpp::version::PlatformVersion;
132 use rand::rngs::StdRng;
133 use rand::SeedableRng;
134
135 #[test]
136 fn test_bls_serialization_deserialization() {
137 let mut rng = StdRng::seed_from_u64(5);
138 let (public_key_data, secret_key) = KeyType::BLS12_381
139 .random_public_and_private_key_data(&mut rng, PlatformVersion::latest())
140 .expect("expected to get keys");
141 let decoded_secret_key =
142 dashcore::blsful::SecretKey::<Bls12381G2Impl>::from_be_bytes(&secret_key)
143 .expect("expected to get secret key");
144 let public_key = decoded_secret_key.public_key();
145 let decoded_public_key_data = public_key.0.to_compressed();
146 assert_eq!(
147 public_key_data.as_slice(),
148 decoded_public_key_data.as_slice()
149 )
150 }
151
152 #[test]
153 fn test_bls_serialization_deserialization_signature() {
154 let mut rng = StdRng::seed_from_u64(5);
155 let (_, secret_key) = KeyType::BLS12_381
156 .random_public_and_private_key_data(&mut rng, PlatformVersion::latest())
157 .expect("expected to get keys");
158 let decoded_secret_key =
159 dashcore::blsful::SecretKey::<Bls12381G2Impl>::from_be_bytes(&secret_key)
160 .expect("expected to get secret key");
161 let signature = decoded_secret_key
162 .sign(SignatureSchemes::Basic, b"hello")
163 .expect("expected to sign");
164 let compressed = signature.as_raw_value().to_compressed();
165 let g2 = <Bls12381G2Impl as Pairing>::Signature::from_compressed(&compressed)
166 .expect("G2 projective");
167 let decoded_signature = Signature::<Bls12381G2Impl>::Basic(g2);
168 assert_eq!(
169 compressed.as_slice(),
170 decoded_signature.as_raw_value().to_compressed().as_slice()
171 )
172 }
173
174 #[cfg(feature = "random-public-keys")]
175 #[test]
176 fn test_validate_private_key_bytes_with_random_keys() {
177 let platform_version = PlatformVersion::latest();
178 let mut rng = StdRng::from_entropy();
179
180 let key_type = KeyType::ECDSA_SECP256K1;
182 let (public_key_data, private_key_data) = key_type
183 .random_public_and_private_key_data(&mut rng, platform_version)
184 .expect("expected to generate random keys");
185
186 let identity_public_key = IdentityPublicKeyV0 {
187 id: 1,
188 purpose: Purpose::AUTHENTICATION,
189 security_level: SecurityLevel::HIGH,
190 contract_bounds: None,
191 key_type,
192 data: public_key_data.into(),
193 read_only: false,
194 disabled_at: None,
195 };
196
197 assert!(identity_public_key
199 .validate_private_key_bytes(&private_key_data, Network::Testnet)
200 .unwrap(),);
201
202 let invalid_private_key_bytes = [0u8; 32];
204 assert!(!identity_public_key
205 .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet)
206 .unwrap());
207 }
208
209 #[cfg(all(feature = "random-public-keys", feature = "bls-signatures"))]
210 #[test]
211 fn test_validate_private_key_bytes_with_random_keys_bls12_381() {
212 let platform_version = PlatformVersion::latest();
213 let mut rng = StdRng::from_entropy();
214
215 let key_type = KeyType::BLS12_381;
217 let (public_key_data, private_key_data) = key_type
218 .random_public_and_private_key_data(&mut rng, platform_version)
219 .expect("expected to generate random keys");
220
221 let identity_public_key = IdentityPublicKeyV0 {
222 id: 2,
223 purpose: Purpose::AUTHENTICATION,
224 security_level: SecurityLevel::HIGH,
225 contract_bounds: None,
226 key_type,
227 data: public_key_data.into(),
228 read_only: false,
229 disabled_at: None,
230 };
231
232 assert!(identity_public_key
234 .validate_private_key_bytes(&private_key_data, Network::Testnet)
235 .unwrap());
236
237 let invalid_private_key_bytes = [0u8; 32];
239 assert!(!identity_public_key
240 .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet)
241 .unwrap());
242 }
243
244 #[cfg(all(feature = "random-public-keys", feature = "ed25519-dalek"))]
245 #[test]
246 fn test_validate_private_key_bytes_with_random_keys_eddsa_25519_hash160() {
247 let platform_version = PlatformVersion::latest();
248 let mut rng = StdRng::from_entropy();
249
250 let key_type = KeyType::EDDSA_25519_HASH160;
252 let (public_key_data, private_key_data) = key_type
253 .random_public_and_private_key_data(&mut rng, platform_version)
254 .expect("expected to generate random keys");
255
256 let identity_public_key = IdentityPublicKeyV0 {
257 id: 3,
258 purpose: Purpose::AUTHENTICATION,
259 security_level: SecurityLevel::HIGH,
260 contract_bounds: None,
261 key_type,
262 data: public_key_data.into(),
263 read_only: false,
264 disabled_at: None,
265 };
266
267 assert!(identity_public_key
269 .validate_private_key_bytes(&private_key_data, Network::Testnet)
270 .unwrap());
271
272 let invalid_private_key_bytes = [0u8; 32];
274 assert!(!identity_public_key
275 .validate_private_key_bytes(&invalid_private_key_bytes, Network::Testnet)
276 .unwrap());
277 }
278}