@@ -140,8 +140,8 @@ func TimeLock(scheme crypto.Scheme, publicKey kyber.Point, roundNumber uint64, d
140140 return TimeLockWithAdditionalData (scheme , publicKey , roundNumber , data , nil )
141141}
142142
143- // TimeLockWithAdditionalData encrypts data with additional context to prevent replay attacks .
144- // The additional data is embedded in the plaintext before encryption .
143+ // TimeLockWithAdditionalData encrypts with additional data for replay attack prevention .
144+ // different AD produces different ciphertexts even for same message .
145145func TimeLockWithAdditionalData (scheme crypto.Scheme , publicKey kyber.Point , roundNumber uint64 , data []byte , additionalData []byte ) (* ibe.Ciphertext , error ) {
146146 if publicKey .Equal (publicKey .Clone ().Null ()) {
147147 return nil , ErrInvalidPublicKey
@@ -155,38 +155,42 @@ func TimeLockWithAdditionalData(scheme crypto.Scheme, publicKey kyber.Point, rou
155155 // Get the ID from the beacon
156156 id := scheme .DigestBeacon (beacon )
157157
158- // Prepend additional data to plaintext if provided
159- var dataToEncrypt []byte
160- if len (additionalData ) > 0 {
161- dataToEncrypt = make ([]byte , 4 + len (additionalData )+ len (data ))
162- // Store length (4 bytes, big-endian)
163- dataToEncrypt [0 ] = byte (len (additionalData ) >> 24 )
164- dataToEncrypt [1 ] = byte (len (additionalData ) >> 16 )
165- dataToEncrypt [2 ] = byte (len (additionalData ) >> 8 )
166- dataToEncrypt [3 ] = byte (len (additionalData ))
167- copy (dataToEncrypt [4 :], additionalData )
168- copy (dataToEncrypt [4 + len (additionalData ):], data )
169- } else {
170- dataToEncrypt = data
171- }
172-
173158 var cipherText * ibe.Ciphertext
174159 var err error
175- switch scheme .Name {
176- case crypto .ShortSigSchemeID :
177- // the ShortSigSchemeID uses the wrong DST for G1, so we keep it for retro-compatibility
178- cipherText , err = ibe .EncryptCCAonG2 (bls .NewBLS12381SuiteWithDST (bls .DefaultDomainG2 (), bls .DefaultDomainG2 ()), publicKey , id , dataToEncrypt )
179- case crypto .UnchainedSchemeID :
180- cipherText , err = ibe .EncryptCCAonG1 (bls .NewBLS12381Suite (), publicKey , id , dataToEncrypt )
181- case crypto .SigsOnG1ID :
182- cipherText , err = ibe .EncryptCCAonG2 (bls .NewBLS12381Suite (), publicKey , id , dataToEncrypt )
183- case crypto .BN254UnchainedOnG1SchemeID :
184- suite := bn .NewSuiteBn254 ()
185- suite .SetDomainG1 ([]byte ("BLS_SIG_BN254G1_XMD:KECCAK-256_SVDW_RO_NUL_" ))
186- suite .SetDomainG2 ([]byte ("BLS_SIG_BN254G2_XMD:KECCAK-256_SVDW_RO_NUL_" ))
187- cipherText , err = ibe .EncryptCCAonG2 (suite , publicKey , id , dataToEncrypt )
188- default :
189- return nil , fmt .Errorf ("unsupported drand scheme '%s'" , scheme .Name )
160+
161+ if len (additionalData ) > 0 {
162+ switch scheme .Name {
163+ case crypto .ShortSigSchemeID :
164+ // the ShortSigSchemeID uses the wrong DST for G1, so we keep it for retro-compatibility
165+ cipherText , err = ibe .EncryptCCAonG2WithAD (bls .NewBLS12381SuiteWithDST (bls .DefaultDomainG2 (), bls .DefaultDomainG2 ()), publicKey , id , data , additionalData )
166+ case crypto .UnchainedSchemeID :
167+ cipherText , err = ibe .EncryptCCAonG1WithAD (bls .NewBLS12381Suite (), publicKey , id , data , additionalData )
168+ case crypto .SigsOnG1ID :
169+ cipherText , err = ibe .EncryptCCAonG2WithAD (bls .NewBLS12381Suite (), publicKey , id , data , additionalData )
170+ case crypto .BN254UnchainedOnG1SchemeID :
171+ suite := bn .NewSuiteBn254 ()
172+ suite .SetDomainG1 ([]byte ("BLS_SIG_BN254G1_XMD:KECCAK-256_SVDW_RO_NUL_" ))
173+ suite .SetDomainG2 ([]byte ("BLS_SIG_BN254G2_XMD:KECCAK-256_SVDW_RO_NUL_" ))
174+ cipherText , err = ibe .EncryptCCAonG2WithAD (suite , publicKey , id , data , additionalData )
175+ default :
176+ return nil , fmt .Errorf ("unsupported drand scheme '%s'" , scheme .Name )
177+ }
178+ } else {
179+ switch scheme .Name {
180+ case crypto .ShortSigSchemeID :
181+ cipherText , err = ibe .EncryptCCAonG2 (bls .NewBLS12381SuiteWithDST (bls .DefaultDomainG2 (), bls .DefaultDomainG2 ()), publicKey , id , data )
182+ case crypto .UnchainedSchemeID :
183+ cipherText , err = ibe .EncryptCCAonG1 (bls .NewBLS12381Suite (), publicKey , id , data )
184+ case crypto .SigsOnG1ID :
185+ cipherText , err = ibe .EncryptCCAonG2 (bls .NewBLS12381Suite (), publicKey , id , data )
186+ case crypto .BN254UnchainedOnG1SchemeID :
187+ suite := bn .NewSuiteBn254 ()
188+ suite .SetDomainG1 ([]byte ("BLS_SIG_BN254G1_XMD:KECCAK-256_SVDW_RO_NUL_" ))
189+ suite .SetDomainG2 ([]byte ("BLS_SIG_BN254G2_XMD:KECCAK-256_SVDW_RO_NUL_" ))
190+ cipherText , err = ibe .EncryptCCAonG2 (suite , publicKey , id , data )
191+ default :
192+ return nil , fmt .Errorf ("unsupported drand scheme '%s'" , scheme .Name )
193+ }
190194 }
191195
192196 if err != nil {
@@ -202,81 +206,91 @@ func TimeUnlock(scheme crypto.Scheme, publicKey kyber.Point, beacon chain.Beacon
202206 return TimeUnlockWithAdditionalData (scheme , publicKey , beacon , ciphertext , nil )
203207}
204208
205- // TimeUnlockWithAdditionalData decrypts ciphertext and verifies the embedded additional data.
209+ // TimeUnlockWithAdditionalData decrypts with additional data verification.
210+ // wrong AD fails at cryptographic level during rP check.
206211func TimeUnlockWithAdditionalData (scheme crypto.Scheme , publicKey kyber.Point , beacon chain.Beacon , ciphertext * ibe.Ciphertext , additionalData []byte ) ([]byte , error ) {
207212 // Verify the beacon first
208213 if err := scheme .VerifyBeacon (& beacon , publicKey ); err != nil {
209214 return nil , fmt .Errorf ("verify beacon: %w" , err )
210215 }
211216
212- // Perform standard IBE decryption
213217 var decryptedData []byte
214218 var err error
215- switch scheme .Name {
216- case crypto .ShortSigSchemeID :
217- var signature bls.KyberG1
218- if err := signature .UnmarshalBinary (beacon .Signature ); err != nil {
219- return nil , fmt .Errorf ("unmarshal kyber G1: %w" , err )
220- }
221- suite := bls .NewBLS12381SuiteWithDST (bls .DefaultDomainG2 (), bls .DefaultDomainG2 ())
222- decryptedData , err = ibe .DecryptCCAonG2 (suite , & signature , ciphertext )
223- case crypto .UnchainedSchemeID :
224- var signature bls.KyberG2
225- if err := signature .UnmarshalBinary (beacon .Signature ); err != nil {
226- return nil , fmt .Errorf ("unmarshal kyber G2: %w" , err )
227- }
228- suite := bls .NewBLS12381Suite ()
229- decryptedData , err = ibe .DecryptCCAonG1 (suite , & signature , ciphertext )
230- case crypto .SigsOnG1ID :
231- var signature bls.KyberG1
232- if err := signature .UnmarshalBinary (beacon .Signature ); err != nil {
233- return nil , fmt .Errorf ("unmarshal kyber G1: %w" , err )
234- }
235- suite := bls .NewBLS12381Suite ()
236- decryptedData , err = ibe .DecryptCCAonG2 (suite , & signature , ciphertext )
237- case crypto .BN254UnchainedOnG1SchemeID :
238- suite := bn .NewSuiteBn254 ()
239- suite .SetDomainG1 ([]byte ("BLS_SIG_BN254G1_XMD:KECCAK-256_SVDW_RO_NUL_" ))
240- suite .SetDomainG2 ([]byte ("BLS_SIG_BN254G2_XMD:KECCAK-256_SVDW_RO_NUL_" ))
241- signature := suite .G1 ().Point ()
242- if err := signature .UnmarshalBinary (beacon .Signature ); err != nil {
243- return nil , fmt .Errorf ("unmarshal kyber G1: %w" , err )
244- }
245- decryptedData , err = ibe .DecryptCCAonG2 (suite , signature , ciphertext )
246- default :
247- return nil , fmt .Errorf ("unsupported drand scheme '%s'" , scheme .Name )
248- }
249219
250- if err != nil {
251- return nil , fmt .Errorf ("decrypt dek: %w" , err )
252- }
253-
254- // Extract and verify additional data if present
255- if len (decryptedData ) >= 4 {
256- potentialAdLen := int (decryptedData [0 ])<< 24 | int (decryptedData [1 ])<< 16 | int (decryptedData [2 ])<< 8 | int (decryptedData [3 ])
257-
258- if potentialAdLen > 0 && potentialAdLen < len (decryptedData ) && len (decryptedData ) >= 4 + potentialAdLen {
259- if len (additionalData ) == 0 {
260- return nil , fmt .Errorf ("ciphertext contains additional data but none was provided for verification" )
220+ if len (additionalData ) > 0 {
221+ switch scheme .Name {
222+ case crypto .ShortSigSchemeID :
223+ var signature bls.KyberG1
224+ if err := signature .UnmarshalBinary (beacon .Signature ); err != nil {
225+ return nil , fmt .Errorf ("unmarshal kyber G1: %w" , err )
261226 }
262-
263- if potentialAdLen != len (additionalData ) {
264- return nil , fmt .Errorf ("additional data length mismatch: expected %d, got %d" , len (additionalData ), potentialAdLen )
227+ suite := bls .NewBLS12381SuiteWithDST (bls .DefaultDomainG2 (), bls .DefaultDomainG2 ())
228+ decryptedData , err = ibe .DecryptCCAonG2WithAD (suite , & signature , ciphertext , additionalData )
229+ case crypto .UnchainedSchemeID :
230+ var signature bls.KyberG2
231+ if err := signature .UnmarshalBinary (beacon .Signature ); err != nil {
232+ return nil , fmt .Errorf ("unmarshal kyber G2: %w" , err )
265233 }
266-
267- embeddedAdditionalData := decryptedData [ 4 : 4 + potentialAdLen ]
268- for i , b := range embeddedAdditionalData {
269- if b != additionalData [ i ] {
270- return nil , fmt . Errorf ( "additional data mismatch at byte %d" , i )
271- }
234+ suite := bls . NewBLS12381Suite ()
235+ decryptedData , err = ibe . DecryptCCAonG1WithAD ( suite , & signature , ciphertext , additionalData )
236+ case crypto . SigsOnG1ID :
237+ var signature bls. KyberG1
238+ if err := signature . UnmarshalBinary ( beacon . Signature ); err != nil {
239+ return nil , fmt . Errorf ( "unmarshal kyber G1: %w" , err )
272240 }
273-
274- return decryptedData [4 + potentialAdLen :], nil
241+ suite := bls .NewBLS12381Suite ()
242+ decryptedData , err = ibe .DecryptCCAonG2WithAD (suite , & signature , ciphertext , additionalData )
243+ case crypto .BN254UnchainedOnG1SchemeID :
244+ suite := bn .NewSuiteBn254 ()
245+ suite .SetDomainG1 ([]byte ("BLS_SIG_BN254G1_XMD:KECCAK-256_SVDW_RO_NUL_" ))
246+ suite .SetDomainG2 ([]byte ("BLS_SIG_BN254G2_XMD:KECCAK-256_SVDW_RO_NUL_" ))
247+ signature := suite .G1 ().Point ()
248+ if err := signature .UnmarshalBinary (beacon .Signature ); err != nil {
249+ return nil , fmt .Errorf ("unmarshal kyber G1: %w" , err )
250+ }
251+ decryptedData , err = ibe .DecryptCCAonG2WithAD (suite , signature , ciphertext , additionalData )
252+ default :
253+ return nil , fmt .Errorf ("unsupported drand scheme '%s'" , scheme .Name )
254+ }
255+ } else {
256+ switch scheme .Name {
257+ case crypto .ShortSigSchemeID :
258+ var signature bls.KyberG1
259+ if err := signature .UnmarshalBinary (beacon .Signature ); err != nil {
260+ return nil , fmt .Errorf ("unmarshal kyber G1: %w" , err )
261+ }
262+ suite := bls .NewBLS12381SuiteWithDST (bls .DefaultDomainG2 (), bls .DefaultDomainG2 ())
263+ decryptedData , err = ibe .DecryptCCAonG2 (suite , & signature , ciphertext )
264+ case crypto .UnchainedSchemeID :
265+ var signature bls.KyberG2
266+ if err := signature .UnmarshalBinary (beacon .Signature ); err != nil {
267+ return nil , fmt .Errorf ("unmarshal kyber G2: %w" , err )
268+ }
269+ suite := bls .NewBLS12381Suite ()
270+ decryptedData , err = ibe .DecryptCCAonG1 (suite , & signature , ciphertext )
271+ case crypto .SigsOnG1ID :
272+ var signature bls.KyberG1
273+ if err := signature .UnmarshalBinary (beacon .Signature ); err != nil {
274+ return nil , fmt .Errorf ("unmarshal kyber G1: %w" , err )
275+ }
276+ suite := bls .NewBLS12381Suite ()
277+ decryptedData , err = ibe .DecryptCCAonG2 (suite , & signature , ciphertext )
278+ case crypto .BN254UnchainedOnG1SchemeID :
279+ suite := bn .NewSuiteBn254 ()
280+ suite .SetDomainG1 ([]byte ("BLS_SIG_BN254G1_XMD:KECCAK-256_SVDW_RO_NUL_" ))
281+ suite .SetDomainG2 ([]byte ("BLS_SIG_BN254G2_XMD:KECCAK-256_SVDW_RO_NUL_" ))
282+ signature := suite .G1 ().Point ()
283+ if err := signature .UnmarshalBinary (beacon .Signature ); err != nil {
284+ return nil , fmt .Errorf ("unmarshal kyber G1: %w" , err )
285+ }
286+ decryptedData , err = ibe .DecryptCCAonG2 (suite , signature , ciphertext )
287+ default :
288+ return nil , fmt .Errorf ("unsupported drand scheme '%s'" , scheme .Name )
275289 }
276290 }
277291
278- if len ( additionalData ) > 0 {
279- return nil , fmt .Errorf ("additional data was provided but ciphertext does not contain any" )
292+ if err != nil {
293+ return nil , fmt .Errorf ("decrypt dek: %w" , err )
280294 }
281295
282296 return decryptedData , nil
0 commit comments