Skip to content

Commit 5ba9120

Browse files
committed
use new kyber AD APIs for tlock commitment
1 parent 4b6c0ed commit 5ba9120

File tree

2 files changed

+265
-92
lines changed

2 files changed

+265
-92
lines changed

tlock.go

Lines changed: 106 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
145145
func 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.
206211
func 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

Comments
 (0)