@@ -3,6 +3,7 @@ use derive_more::Constructor;
3
3
use near_sdk:: PublicKey ;
4
4
use serde:: { Deserialize , Serialize } ;
5
5
use sha3:: { Digest , Sha3_384 } ;
6
+ use alloc:: vec;
6
7
7
8
/// Number of bytes for the report data.
8
9
const REPORT_DATA_SIZE : usize = 64 ;
@@ -36,10 +37,11 @@ impl ReportDataVersion {
36
37
#[ derive( Debug , Clone , Constructor ) ]
37
38
pub struct ReportDataV1 {
38
39
tls_public_key : PublicKey ,
40
+ account_public_key : PublicKey ,
39
41
}
40
42
41
43
/// report_data_v1: [u8; 64] =
42
- /// [version(2 bytes big endian) || sha384(TLS pub key) || zero padding]
44
+ /// [version(2 bytes big endian) || sha384(TLS pub key || account_pubkey ) || zero padding]
43
45
impl ReportDataV1 {
44
46
/// V1-specific format constants
45
47
const PUBLIC_KEYS_OFFSET : usize = BINARY_VERSION_OFFSET + BINARY_VERSION_SIZE ;
@@ -84,12 +86,18 @@ impl ReportDataV1 {
84
86
hash
85
87
}
86
88
87
- /// Generates SHA3-384 hash of TLS public key only .
89
+ /// Generates SHA3-384 hash of TLS + NEAR account keys together .
88
90
fn public_keys_hash ( & self ) -> [ u8 ; Self :: PUBLIC_KEYS_HASH_SIZE ] {
89
91
let mut hasher = Sha3_384 :: new ( ) ;
90
- // Skip first byte as it is used for identifier for the curve type.
91
- let key_data = & self . tls_public_key . as_bytes ( ) [ 1 ..] ;
92
- hasher. update ( key_data) ;
92
+
93
+ // Hash TLS key (skip first byte = curve type)
94
+ let tls_data = & self . tls_public_key . as_bytes ( ) [ 1 ..] ;
95
+ hasher. update ( tls_data) ;
96
+
97
+ // Hash NEAR account key (also skip first byte)
98
+ let account_data = & self . account_public_key . as_bytes ( ) [ 1 ..] ;
99
+ hasher. update ( account_data) ;
100
+
93
101
hasher. finalize ( ) . into ( )
94
102
}
95
103
}
@@ -100,8 +108,13 @@ pub enum ReportData {
100
108
}
101
109
102
110
impl ReportData {
103
- pub fn new ( tls_public_key : PublicKey ) -> Self {
104
- ReportData :: V1 ( ReportDataV1 :: new ( tls_public_key) )
111
+ pub fn new ( tls_public_key : PublicKey , account_public_key : Option < PublicKey > ) -> Self {
112
+ let account_pk = account_public_key. unwrap_or_else ( || {
113
+ // Construct a "zero" public key. will not be used in practice, only for backward compatibility. remove this code once that network enforces real attestation
114
+ PublicKey :: from_parts ( near_sdk:: CurveType :: ED25519 , vec ! [ 0u8 ; 32 ] ) . expect ( "valid zero PublicKey" )
115
+ } ) ;
116
+
117
+ ReportData :: V1 ( ReportDataV1 :: new ( tls_public_key, account_pk) )
105
118
}
106
119
107
120
pub fn version ( & self ) -> ReportDataVersion {
@@ -125,8 +138,15 @@ mod tests {
125
138
use alloc:: vec:: Vec ;
126
139
use dcap_qvl:: quote:: Quote ;
127
140
use near_sdk:: PublicKey ;
141
+ use sha3:: { Digest , Sha3_384 } ;
128
142
use test_utils:: attestation:: { p2p_tls_key, quote} ;
129
143
144
+ fn create_test_key ( ) -> PublicKey {
145
+ "secp256k1:qMoRgcoXai4mBPsdbHi1wfyxF9TdbPCF4qSDQTRP3TfescSRoUdSx6nmeQoN3aiwGzwMyGXAb1gUjBTv5AY8DXj"
146
+ . parse ( )
147
+ . unwrap ( )
148
+ }
149
+
130
150
#[ test]
131
151
fn test_from_str_valid ( ) {
132
152
let valid_quote: Vec < u8 > =
@@ -136,14 +156,9 @@ mod tests {
136
156
let td_report = quote. report . as_td10 ( ) . expect ( "Should be a TD 1.0 report" ) ;
137
157
138
158
let near_p2p_public_key: PublicKey = p2p_tls_key ( ) ;
139
- let report_data = ReportData :: V1 ( ReportDataV1 :: new ( near_p2p_public_key) ) ;
140
- assert_eq ! ( report_data. to_bytes( ) , td_report. report_data, ) ;
141
- }
142
-
143
- fn create_test_key ( ) -> PublicKey {
144
- "secp256k1:qMoRgcoXai4mBPsdbHi1wfyxF9TdbPCF4qSDQTRP3TfescSRoUdSx6nmeQoN3aiwGzwMyGXAb1gUjBTv5AY8DXj"
145
- . parse ( )
146
- . unwrap ( )
159
+ let account_key = create_test_key ( ) ;
160
+ let report_data = ReportData :: V1 ( ReportDataV1 :: new ( near_p2p_public_key, account_key) ) ;
161
+ assert_eq ! ( report_data. to_bytes( ) , td_report. report_data) ;
147
162
}
148
163
149
164
#[ test]
@@ -160,11 +175,13 @@ mod tests {
160
175
#[ test]
161
176
fn test_report_data_enum_structure ( ) {
162
177
let tls_key = create_test_key ( ) ;
163
- let data = ReportData :: V1 ( ReportDataV1 :: new ( tls_key. clone ( ) ) ) ;
178
+ let account_key = create_test_key ( ) ;
179
+ let data = ReportData :: V1 ( ReportDataV1 :: new ( tls_key. clone ( ) , account_key. clone ( ) ) ) ;
164
180
165
181
match & data {
166
182
ReportData :: V1 ( v1) => {
167
183
assert_eq ! ( & v1. tls_public_key, & tls_key) ;
184
+ assert_eq ! ( & v1. account_public_key, & account_key) ;
168
185
}
169
186
}
170
187
@@ -174,15 +191,18 @@ mod tests {
174
191
#[ test]
175
192
fn test_report_data_v1_struct ( ) {
176
193
let tls_key = create_test_key ( ) ;
194
+ let account_key = create_test_key ( ) ;
177
195
178
- let v1 = ReportDataV1 :: new ( tls_key. clone ( ) ) ;
196
+ let v1 = ReportDataV1 :: new ( tls_key. clone ( ) , account_key . clone ( ) ) ;
179
197
assert_eq ! ( v1. tls_public_key, tls_key) ;
198
+ assert_eq ! ( v1. account_public_key, account_key) ;
180
199
}
181
200
182
201
#[ test]
183
202
fn test_from_bytes ( ) {
184
203
let tls_key = create_test_key ( ) ;
185
- let report_data_v1 = ReportDataV1 :: new ( tls_key) ;
204
+ let account_key = create_test_key ( ) ;
205
+ let report_data_v1 = ReportDataV1 :: new ( tls_key. clone ( ) , account_key. clone ( ) ) ;
186
206
let bytes = report_data_v1. to_bytes ( ) ;
187
207
188
208
let hash = ReportDataV1 :: from_bytes ( & bytes) ;
@@ -195,7 +215,8 @@ mod tests {
195
215
#[ test]
196
216
fn test_binary_version_placement ( ) {
197
217
let tls_key = create_test_key ( ) ;
198
- let bytes = ReportDataV1 :: new ( tls_key) . to_bytes ( ) ;
218
+ let account_key = create_test_key ( ) ;
219
+ let bytes = ReportDataV1 :: new ( tls_key, account_key) . to_bytes ( ) ;
199
220
200
221
let version_bytes =
201
222
& bytes[ BINARY_VERSION_OFFSET ..BINARY_VERSION_OFFSET + BINARY_VERSION_SIZE ] ;
@@ -205,20 +226,21 @@ mod tests {
205
226
#[ test]
206
227
fn test_public_key_hash_placement ( ) {
207
228
let tls_key = create_test_key ( ) ;
208
- let report_data_v1 = ReportDataV1 :: new ( tls_key. clone ( ) ) ;
229
+ let account_key = create_test_key ( ) ;
230
+ let report_data_v1 = ReportDataV1 :: new ( tls_key. clone ( ) , account_key. clone ( ) ) ;
209
231
let bytes = report_data_v1. to_bytes ( ) ;
210
232
211
- let report_data = ReportData :: V1 ( report_data_v1) ;
233
+ let report_data = ReportData :: V1 ( report_data_v1. clone ( ) ) ;
212
234
assert_eq ! ( report_data. to_bytes( ) , bytes) ;
213
235
214
236
let hash_bytes = & bytes[ ReportDataV1 :: PUBLIC_KEYS_OFFSET
215
237
..ReportDataV1 :: PUBLIC_KEYS_OFFSET + ReportDataV1 :: PUBLIC_KEYS_HASH_SIZE ] ;
216
238
assert_ne ! ( hash_bytes, & [ 0u8 ; ReportDataV1 :: PUBLIC_KEYS_HASH_SIZE ] ) ;
217
239
240
+ // Expected hash = sha3_384(tls || account)
218
241
let mut hasher = Sha3_384 :: new ( ) ;
219
- // Skip first byte as it is used for identifier for the curve type.
220
- let key_data = & tls_key. as_bytes ( ) [ 1 ..] ;
221
- hasher. update ( key_data) ;
242
+ hasher. update ( & tls_key. as_bytes ( ) [ 1 ..] ) ;
243
+ hasher. update ( & account_key. as_bytes ( ) [ 1 ..] ) ;
222
244
let expected: [ u8 ; ReportDataV1 :: PUBLIC_KEYS_HASH_SIZE ] = hasher. finalize ( ) . into ( ) ;
223
245
224
246
assert_eq ! ( hash_bytes, & expected) ;
@@ -227,7 +249,8 @@ mod tests {
227
249
#[ test]
228
250
fn test_zero_padding ( ) {
229
251
let tls_key = create_test_key ( ) ;
230
- let bytes = ReportDataV1 :: new ( tls_key) . to_bytes ( ) ;
252
+ let account_key = create_test_key ( ) ;
253
+ let bytes = ReportDataV1 :: new ( tls_key, account_key) . to_bytes ( ) ;
231
254
232
255
let padding =
233
256
& bytes[ ReportDataV1 :: PUBLIC_KEYS_OFFSET + ReportDataV1 :: PUBLIC_KEYS_HASH_SIZE ..] ;
@@ -237,7 +260,8 @@ mod tests {
237
260
#[ test]
238
261
fn test_report_data_size ( ) {
239
262
let tls_key = create_test_key ( ) ;
240
- let bytes = ReportDataV1 :: new ( tls_key) ;
263
+ let account_key = create_test_key ( ) ;
264
+ let bytes = ReportDataV1 :: new ( tls_key, account_key) ;
241
265
assert_eq ! ( bytes. to_bytes( ) . len( ) , REPORT_DATA_SIZE ) ;
242
266
}
243
267
}
0 commit comments