-
I'm totally a beginner with zk and gnark, and I want to generate a BLS12381 point and a Secp256k1 point in a circuit, but I come up with some problems. The proposal is to verify an encryption of a BLS12381 scalar with a Secp256k1 public key, and the idea is to use the same bigint value to generate a BLS12381 point for commitment and a Secp256k1 point for encryption. So I have a secret bigint To realize this, I tried the following codes to encrypt a bigint. type EccCircuit[Secp256k1Fp, Secp256k1Fr emulated.FieldParams] struct {
Msg frontend.Variable
R frontend.Variable `gnark:",public"`
Cpr CipherText[Secp256k1Fp] `gnark:",public"`
Pub PublicKey[Secp256k1Fp, Secp256k1Fr] `gnark:",public"`
}
func (c *EccCircuit[Secp256k1Fp, Secp256k1Fr]) Define(api frontend.API) error {
c.Pub.VerifyEncrypt(api, sw_emulated.GetCurveParams[Secp256k1Fp](), c.Msg, c.R, c.Cpr)
return nil
}
type PublicKey[Secp256k1Fp, Secp256k1Fr emulated.FieldParams] sw_emulated.AffinePoint[Secp256k1Fp]
type CipherText[Secp256k1Fp emulated.FieldParams] struct {
C, R sw_emulated.AffinePoint[Secp256k1Fp]
}
func (pk PublicKey[Secp256k1Fp, Secp256k1Fr]) VerifyEncrypt(
api frontend.API,
params sw_emulated.CurveParams,
msg frontend.Variable,
r frontend.Variable,
cipher CipherText[Secp256k1Fp],
) {
cr, err := sw_emulated.New[Secp256k1Fp, Secp256k1Fr](api, params)
if err != nil {
panic(err)
}
baseApi, err := emulated.NewField[Secp256k1Fp](api)
if err != nil {
panic(err)
}
// Convert bigint to scalar
scalarM := ToFieldElement[Secp256k1Fr](api, msg)
scalarR := ToFieldElement[Secp256k1Fr](api, r)
// C = M + rpk
pkpt := sw_emulated.AffinePoint[Secp256k1Fp](pk)
bigR := cr.ScalarMulBase(scalarR)
bigC := cr.JointScalarMulBase(&pkpt, scalarR, scalarM)
rx := baseApi.Reduce(&bigR.X)
rxBits := baseApi.ToBits(rx)
rbits := baseApi.ToBits(&cipher.R.X)
if len(rbits) != len(rxBits) {
panic("non-equal lengths")
}
for i := range rbits {
api.AssertIsEqual(rbits[i], rxBits[i])
}
cx := baseApi.Reduce(&bigC.X)
cxBits := baseApi.ToBits(cx)
cbits := baseApi.ToBits(&cipher.C.X)
if len(cbits) != len(cxBits) {
panic("non-equal lengths")
}
for i := range cbits {
api.AssertIsEqual(cbits[i], cxBits[i])
}
}
func ToFieldElement[Fr emulated.FieldParams](api frontend.API, input frontend.Variable) *emulated.Element[Fr] {
f, err := emulated.NewField[Fr](api)
if err != nil {
panic(err)
}
return f.NewElement(input)
} I used The test with So how can I pass in a |
Beta Was this translation helpful? Give feedback.
Now, when working in-circuit we have a slight problem - we strongly type the field elements. So it means that
emulated.Element[Secp256k1Fr]
is not directly comparable toemulated.Element[BLS12381Fr]
even if the integer values are the same. To perform integer comparison you have to convert the value from one field to another using binary decomposition.