@@ -3,6 +3,8 @@ use std::convert::TryFrom;
3
3
use alloc:: vec;
4
4
use alloc:: vec:: Vec ;
5
5
use parity_scale_codec:: { Decode , Encode , Error as CodecError } ;
6
+ use sp_core:: { H160 , H256 } ;
7
+ use sp_runtime:: AccountId32 ;
6
8
7
9
use crate :: prpc:: { Signature , SignatureType } ;
8
10
pub use phala_crypto:: { aead, ecdh, CryptoError } ;
@@ -72,7 +74,7 @@ impl Signature {
72
74
msg_type : MessageType ,
73
75
current_block : u32 ,
74
76
max_depth : u32 ,
75
- ) -> Result < Vec < Vec < u8 > > , SignatureVerifyError > {
77
+ ) -> Result < Vec < AccountId32 > , SignatureVerifyError > {
76
78
if max_depth == 0 {
77
79
return Err ( SignatureVerifyError :: TooLongCertificateChain ) ;
78
80
}
@@ -92,21 +94,21 @@ impl Signature {
92
94
return Err ( SignatureVerifyError :: CertificateExpired ) ;
93
95
}
94
96
95
- let pubkey = body. recover ( msg, msg_type, sig_type, & self . signature ) ?;
97
+ let body_signer = body. recover ( msg, msg_type, sig_type, & self . signature ) ?;
96
98
97
- let key_chain = if let Some ( cert_sig) = & cert. signature {
98
- let mut key_chain = cert_sig. verify (
99
+ let signers = if let Some ( cert_sig) = & cert. signature {
100
+ let mut signers = cert_sig. verify (
99
101
& body. encode ( ) ,
100
102
MessageType :: Certificate { ttl : body. ttl } ,
101
103
current_block,
102
104
max_depth - 1 ,
103
105
) ?;
104
- key_chain . push ( pubkey ) ;
105
- key_chain
106
+ signers . push ( body_signer ) ;
107
+ signers
106
108
} else {
107
- vec ! [ pubkey ]
109
+ vec ! [ body_signer ]
108
110
} ;
109
- Ok ( key_chain )
111
+ Ok ( signers )
110
112
}
111
113
None => Err ( SignatureVerifyError :: CertificateMissing ) ,
112
114
}
@@ -129,14 +131,17 @@ where
129
131
}
130
132
131
133
/// Dummy "recover" function to verify the Substrate signatures and return the public key
132
- fn recover < T > ( pubkey : & [ u8 ] , sig : & [ u8 ] , msg : & [ u8 ] ) -> Result < Vec < u8 > , SignatureVerifyError >
134
+ fn recover < T > ( pubkey : & [ u8 ] , sig : & [ u8 ] , msg : & [ u8 ] ) -> Result < T :: Public , SignatureVerifyError >
133
135
where
134
136
T : sp_core:: crypto:: Pair ,
135
137
T :: Public : for < ' a > TryFrom < & ' a [ u8 ] > ,
136
138
T :: Signature : for < ' a > TryFrom < & ' a [ u8 ] > ,
137
139
{
140
+ let Ok ( public) = T :: Public :: try_from ( pubkey) else {
141
+ return Err ( SignatureVerifyError :: InvalidPublicKey ) ;
142
+ } ;
138
143
verify :: < T > ( pubkey, sig, msg)
139
- . then_some ( pubkey . to_vec ( ) )
144
+ . then_some ( public )
140
145
. ok_or ( SignatureVerifyError :: InvalidSignature )
141
146
}
142
147
@@ -153,15 +158,47 @@ fn wrap_bytes(msg: &[u8]) -> Vec<u8> {
153
158
fn evm_ecdsa_recover (
154
159
mut signature : [ u8 ; 65 ] ,
155
160
message_hash : [ u8 ; 32 ] ,
156
- ) -> Result < Vec < u8 > , SignatureVerifyError > {
161
+ ) -> Result < sp_core :: ecdsa :: Public , SignatureVerifyError > {
157
162
if signature[ 64 ] >= 27 {
158
163
signature[ 64 ] -= 27 ;
159
164
}
160
165
let signature = sp_core:: ecdsa:: Signature :: from_raw ( signature) ;
161
166
let recovered_pubkey = signature
162
167
. recover_prehashed ( & message_hash)
163
168
. ok_or ( SignatureVerifyError :: InvalidSignature ) ?;
164
- Ok ( recovered_pubkey. as_ref ( ) . to_vec ( ) )
169
+ Ok ( recovered_pubkey)
170
+ }
171
+
172
+ /// Convert EVM public key to Substrate account ID.
173
+ ///
174
+ /// account_id = keccak256(pubkey)[12..] + b"@evm_address"
175
+ fn account_id_from_evm_pubkey ( pubkey : sp_core:: ecdsa:: Public ) -> AccountId32 {
176
+ let pubkey =
177
+ secp256k1:: PublicKey :: from_slice ( pubkey. as_ref ( ) ) . expect ( "Should always be a valid pubkey" ) ;
178
+ let h32 = H256 ( sp_core:: hashing:: keccak_256 (
179
+ & pubkey. serialize_uncompressed ( ) [ 1 ..] ,
180
+ ) ) ;
181
+ let h20 = H160 :: from ( h32) ;
182
+ let mut raw_account: [ u8 ; 32 ] = [ 0 ; 32 ] ;
183
+ let postfix = b"@evm_address" ;
184
+ raw_account[ ..20 ] . copy_from_slice ( h20. as_bytes ( ) ) ;
185
+ raw_account[ 20 ..] . copy_from_slice ( postfix) ;
186
+ AccountId32 :: from ( raw_account)
187
+ }
188
+
189
+ #[ test]
190
+ fn test_account_id_from_evm_pubkey ( ) {
191
+ let pubkey = sp_core:: ecdsa:: Public ( hex_literal:: hex!(
192
+ "029df1e69b8b7c2da2efe0069dc141c2cec0317bf3fd135abaeb69ee33801f5970"
193
+ ) ) ;
194
+ let account_id = account_id_from_evm_pubkey ( pubkey) ;
195
+ assert_eq ! (
196
+ hex:: encode( account_id) ,
197
+ format!(
198
+ "77bb3d64ea13e4f0beafdd5d92508d4643bb09cb{}" ,
199
+ hex:: encode( b"@evm_address" )
200
+ )
201
+ ) ;
165
202
}
166
203
167
204
#[ derive( Clone , Encode , Decode , Debug ) ]
@@ -178,28 +215,39 @@ impl CertificateBody {
178
215
msg_type : MessageType ,
179
216
sig_type : SignatureType ,
180
217
signature : & [ u8 ] ,
181
- ) -> Result < Vec < u8 > , SignatureVerifyError > {
182
- match sig_type {
218
+ ) -> Result < AccountId32 , SignatureVerifyError > {
219
+ let signer = match sig_type {
183
220
SignatureType :: Ed25519 => {
184
- recover :: < sp_core:: ed25519:: Pair > ( & self . pubkey , signature, msg)
221
+ recover :: < sp_core:: ed25519:: Pair > ( & self . pubkey , signature, msg) ? . into ( )
185
222
}
186
223
SignatureType :: Sr25519 => {
187
- recover :: < sp_core:: sr25519:: Pair > ( & self . pubkey , signature, msg)
224
+ recover :: < sp_core:: sr25519:: Pair > ( & self . pubkey , signature, msg) ? . into ( )
188
225
}
189
- SignatureType :: Ecdsa => recover :: < sp_core:: ecdsa:: Pair > ( & self . pubkey , signature, msg) ,
226
+ SignatureType :: Ecdsa => account_id_from_evm_pubkey ( recover :: < sp_core:: ecdsa:: Pair > (
227
+ & self . pubkey ,
228
+ signature,
229
+ msg,
230
+ ) ?) ,
190
231
SignatureType :: Ed25519WrapBytes => {
191
232
let wrapped = wrap_bytes ( msg) ;
192
- recover :: < sp_core:: ed25519:: Pair > ( & self . pubkey , signature, & wrapped)
233
+ recover :: < sp_core:: ed25519:: Pair > ( & self . pubkey , signature, & wrapped) ? . into ( )
193
234
}
194
235
SignatureType :: Sr25519WrapBytes => {
195
236
let wrapped = wrap_bytes ( msg) ;
196
- recover :: < sp_core:: sr25519:: Pair > ( & self . pubkey , signature, & wrapped)
237
+ recover :: < sp_core:: sr25519:: Pair > ( & self . pubkey , signature, & wrapped) ? . into ( )
197
238
}
198
239
SignatureType :: EcdsaWrapBytes => {
199
240
let wrapped = wrap_bytes ( msg) ;
200
- recover :: < sp_core:: ecdsa:: Pair > ( & self . pubkey , signature, & wrapped)
241
+ account_id_from_evm_pubkey ( recover :: < sp_core:: ecdsa:: Pair > (
242
+ & self . pubkey ,
243
+ signature,
244
+ & wrapped,
245
+ ) ?)
201
246
}
202
- SignatureType :: Eip712 => eip712:: recover ( & self . pubkey , signature, msg, msg_type) ,
203
- }
247
+ SignatureType :: Eip712 => {
248
+ account_id_from_evm_pubkey ( eip712:: recover ( & self . pubkey , signature, msg, msg_type) ?)
249
+ }
250
+ } ;
251
+ Ok ( signer)
204
252
}
205
253
}
0 commit comments