@@ -14,6 +14,54 @@ use bitcoin::secp256k1;
1414use tiny_keccak:: { Hasher , Keccak } ;
1515use util:: test_initialized_simulators;
1616
17+ const EIP712_MSG : & str = r#"
18+ {
19+ "types": {
20+ "EIP712Domain": [
21+ { "name": "name", "type": "string" },
22+ { "name": "version", "type": "string" },
23+ { "name": "chainId", "type": "uint256" },
24+ { "name": "verifyingContract", "type": "address" }
25+ ],
26+ "Attachment": [
27+ { "name": "contents", "type": "string" }
28+ ],
29+ "Person": [
30+ { "name": "name", "type": "string" },
31+ { "name": "wallet", "type": "address" },
32+ { "name": "age", "type": "uint8" }
33+ ],
34+ "Mail": [
35+ { "name": "from", "type": "Person" },
36+ { "name": "to", "type": "Person" },
37+ { "name": "contents", "type": "string" },
38+ { "name": "attachments", "type": "Attachment[]" }
39+ ]
40+ },
41+ "primaryType": "Mail",
42+ "domain": {
43+ "name": "Ether Mail",
44+ "version": "1",
45+ "chainId": 1,
46+ "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
47+ },
48+ "message": {
49+ "from": {
50+ "name": "Cow",
51+ "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
52+ "age": 20
53+ },
54+ "to": {
55+ "name": "Bob",
56+ "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB",
57+ "age": "0x1e"
58+ },
59+ "contents": "Hello, Bob!",
60+ "attachments": [{ "contents": "attachment1" }, { "contents": "attachment2" }]
61+ }
62+ }
63+ "# ;
64+
1765fn keccak256 ( data : & [ u8 ] ) -> [ u8 ; 32 ] {
1866 let mut hasher = Keccak :: v256 ( ) ;
1967 hasher. update ( data) ;
@@ -201,3 +249,66 @@ async fn test_eth_sign_1559_transaction_streaming() {
201249 } )
202250 . await
203251}
252+
253+ #[ tokio:: test]
254+ async fn test_eth_sign_typed_message_antiklepto_enabled ( ) {
255+ test_initialized_simulators ( async |paired_bitbox| {
256+ let signature_antiklepto_1 = paired_bitbox
257+ . eth_sign_typed_message ( 1 , & "m/44'/60'/0'/0/0" . try_into ( ) . unwrap ( ) , EIP712_MSG , true )
258+ . await
259+ . unwrap ( ) ;
260+ let signature_antiklepto_2 = paired_bitbox
261+ . eth_sign_typed_message ( 1 , & "m/44'/60'/0'/0/0" . try_into ( ) . unwrap ( ) , EIP712_MSG , true )
262+ . await
263+ . unwrap ( ) ;
264+ assert_eq ! ( signature_antiklepto_1. len( ) , 65 ) ;
265+ assert_eq ! ( signature_antiklepto_2. len( ) , 65 ) ;
266+ assert_ne ! ( signature_antiklepto_1, signature_antiklepto_2) ;
267+ } )
268+ . await
269+ }
270+
271+ #[ tokio:: test]
272+ async fn test_eth_sign_typed_message_antiklepto_disabled ( ) {
273+ test_initialized_simulators ( async |paired_bitbox| {
274+ if semver:: VersionReq :: parse ( ">=9.26.0" )
275+ . unwrap ( )
276+ . matches ( paired_bitbox. version ( ) )
277+ {
278+ let signature_no_antiklepto_1 = paired_bitbox
279+ . eth_sign_typed_message (
280+ 1 ,
281+ & "m/44'/60'/0'/0/0" . try_into ( ) . unwrap ( ) ,
282+ EIP712_MSG ,
283+ false ,
284+ )
285+ . await
286+ . unwrap ( ) ;
287+ let signature_no_antiklepto_2 = paired_bitbox
288+ . eth_sign_typed_message (
289+ 1 ,
290+ & "m/44'/60'/0'/0/0" . try_into ( ) . unwrap ( ) ,
291+ EIP712_MSG ,
292+ false ,
293+ )
294+ . await
295+ . unwrap ( ) ;
296+ assert_eq ! ( signature_no_antiklepto_1. len( ) , 65 ) ;
297+ assert_eq ! ( signature_no_antiklepto_2. len( ) , 65 ) ;
298+ assert_eq ! ( signature_no_antiklepto_1, signature_no_antiklepto_2) ;
299+ return ;
300+ }
301+
302+ let err = paired_bitbox
303+ . eth_sign_typed_message (
304+ 1 ,
305+ & "m/44'/60'/0'/0/0" . try_into ( ) . unwrap ( ) ,
306+ EIP712_MSG ,
307+ false ,
308+ )
309+ . await
310+ . unwrap_err ( ) ;
311+ assert ! ( matches!( err, bitbox_api:: error:: Error :: Version ( ">=9.26.0" ) ) ) ;
312+ } )
313+ . await
314+ }
0 commit comments