@@ -32,6 +32,7 @@ import { Cip30DataSignature } from '@cardano-sdk/dapp-connector';
32
32
import { HID } from 'node-hid' ;
33
33
import { HexBlob , areNumbersEqualInConstantTime , areStringsEqualInConstantTime } from '@cardano-sdk/util' ;
34
34
import { LedgerDevice , LedgerTransportType } from './types' ;
35
+ import { blake2b } from '@cardano-sdk/crypto' ;
35
36
import { getFirstLedgerDevice } from '@ledgerhq/hw-transport-webusb/lib/webusb' ;
36
37
import { str_to_path } from '@cardano-foundation/ledgerjs-hw-app-cardano/dist/utils/address' ;
37
38
import { toLedgerTx } from './transformers' ;
@@ -66,9 +67,38 @@ const LedgerConnection = (_LedgerConnection as any).default
66
67
: _LedgerConnection ;
67
68
type LedgerConnection = _LedgerConnection ;
68
69
70
+ const CIP08_SIGN_HASH_THRESHOLD = 100 ;
71
+
69
72
const isUsbDevice = ( device : any ) : device is USBDevice =>
70
73
typeof USBDevice !== 'undefined' && device instanceof USBDevice ;
71
74
75
+ /* Sets the hashed entry in the COSESign1 CBOR structure */
76
+ const setCOSESignHashed = ( COSESignCbor : string , isHashed : boolean ) => {
77
+ const reader = new Serialization . CborReader ( HexBlob ( COSESignCbor ) ) ;
78
+ reader . readStartArray ( ) ;
79
+
80
+ const headers = reader . readEncodedValue ( ) ;
81
+ // Skip hashed entry
82
+ reader . readEncodedValue ( ) ;
83
+ const payload = reader . readEncodedValue ( ) ;
84
+ const signature = reader . readEncodedValue ( ) ;
85
+
86
+ reader . readEndArray ( ) ;
87
+
88
+ const writer = new Serialization . CborWriter ( ) ;
89
+
90
+ writer . writeStartArray ( 4 ) ;
91
+ writer . writeEncodedValue ( headers ) ;
92
+ writer . writeStartMap ( 1 ) ;
93
+ writer . writeTextString ( 'hashed' ) ;
94
+ writer . writeBoolean ( isHashed ) ;
95
+
96
+ writer . writeEncodedValue ( payload ) ;
97
+ writer . writeEncodedValue ( signature ) ;
98
+
99
+ return writer . encodeAsHex ( ) ;
100
+ } ;
101
+
72
102
const isDeviceAlreadyOpenError = ( error : unknown ) => {
73
103
if ( typeof error !== 'object' ) return false ;
74
104
const innerError = ( error as any ) . innerError ;
@@ -780,6 +810,7 @@ export class LedgerKeyAgent extends KeyAgentBase {
780
810
}
781
811
782
812
async signCip8Data ( request : cip8 . Cip8SignDataContext ) : Promise < Cip30DataSignature > {
813
+ const hashPayload = request . payload . length >= CIP08_SIGN_HASH_THRESHOLD ;
783
814
try {
784
815
const dRepPublicKey = await this . derivePublicKey ( util . DREP_KEY_DERIVATION_PATH ) ;
785
816
const dRepKeyHashHex = ( await Crypto . Ed25519PublicKey . fromHex ( dRepPublicKey ) . hash ( ) ) . hex ( ) ;
@@ -797,9 +828,8 @@ export class LedgerKeyAgent extends KeyAgentBase {
797
828
? {
798
829
address : addressParams ,
799
830
addressFieldType : MessageAddressFieldType . ADDRESS ,
800
- hashPayload : false ,
831
+ hashPayload,
801
832
messageHex : request . payload ,
802
-
803
833
network : {
804
834
networkId : this . chainId . networkId ,
805
835
protocolMagic : this . chainId . networkMagic
@@ -809,7 +839,7 @@ export class LedgerKeyAgent extends KeyAgentBase {
809
839
}
810
840
: {
811
841
addressFieldType : MessageAddressFieldType . KEY_HASH ,
812
- hashPayload : false ,
842
+ hashPayload,
813
843
messageHex : request . payload ,
814
844
preferHexDisplay : false ,
815
845
signingPath
@@ -830,18 +860,20 @@ export class LedgerKeyAgent extends KeyAgentBase {
830
860
protectedHeaders . set_algorithm_id ( Label . from_algorithm_id ( AlgorithmId . EdDSA ) ) ;
831
861
protectedHeaders . set_header ( cip8 . CoseLabel . address , CBORValue . new_bytes ( addressBytes ) ) ;
832
862
863
+ const sigPayload = coreUtils . hexToBytes ( hashPayload ? blake2b . hash ( request . payload , 28 ) : request . payload ) ;
833
864
const builder = COSESign1Builder . new (
834
865
Headers . new ( ProtectedHeaderMap . new ( protectedHeaders ) , HeaderMap . new ( ) ) ,
835
- coreUtils . hexToBytes ( request . payload ) ,
866
+ sigPayload ,
836
867
false
837
868
) ;
838
869
839
870
const coseSign1 = builder . build ( Buffer . from ( result . signatureHex , 'hex' ) ) ;
840
871
const coseKey = cip8 . createCoseKey ( addressBytes , Crypto . Ed25519PublicKeyHex ( result . signingPublicKeyHex ) ) ;
841
872
873
+ const coseSigHex = coreUtils . bytesToHex ( coseSign1 . to_bytes ( ) ) ;
842
874
return {
843
875
key : coreUtils . bytesToHex ( coseKey . to_bytes ( ) ) ,
844
- signature : coreUtils . bytesToHex ( coseSign1 . to_bytes ( ) )
876
+ signature : hashPayload ? setCOSESignHashed ( coseSigHex , true ) : coseSigHex
845
877
} ;
846
878
} catch ( error : any ) {
847
879
if ( error . code === 28_169 ) {
0 commit comments