zkcrypto / pairing

Pairing-friendly elliptic curve library.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Troubles with Fq::pow

mmaker opened this issue · comments

Hello!
I'm trying to get Fq::pow to work, but it seems I can't get it right… is this me or is it really a bug?
This is what I can get to do with sage:

sage: def h(x): return hex(int(x))[:-1] # this is only to get a confrontable hex representation 
sage: q = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787
sage: Fq = GF(q)
sage: h(q)
'0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab'
sage: a = Fq(945268695322731484897977891916087812827587793626675745004848628347665446205888379878456193299686130571287070888667)
sage: h(a)
'0x6243b9d40ce4d8c1d86a603d9ce33eb76736fc8900b1e8da6de01cbdb27177539b472f83366efa4ed5bf6438391d2db'
sage: a**9
1183374762412757565163659156070127511863449313069977006820839763739586492957873774713939591053070945417445562515423
sage: h(a**9)
'0x7b04438ade27f8f2b916ebad4ad86d3941f87b5bbb022113edcf19384b6892c9e5fa522f8d60ab97d5c4ef522adffdf'

but if I attempt to add the following test case to fq.rs:

#[test]
fn test_pow_bug() {
    let e = Fq(FqRepr([0xd5bf6438391d2db, 0x9b472f83366efa4e, 0x6de01cbdb2717753,
                       0x6736fc8900b1e8da, 0xd86a603d9ce33eb7, 0x6243b9d40ce4d8c1]));
    let expected = Fq(FqRepr([0xd5c4ef522adffdf, 0xe5fa522f8d60ab97, 0xedcf19384b6892c9,
                              0x41f87b5bbb022113, 0xb916ebad4ad86d39, 0x7b04438ade27f8f2]));

    let got = e.pow([0x9, 0x0, 0x0, 0x0, 0x0, 0x0]);
    assert_eq!(got, expected)

the test fails:

---- bls12_381::fq::test_pow_bug stdout ----               
        thread 'bls12_381::fq::test_pow_bug' panicked at 'assertion failed: `(left == right)`                          
  left: `Fq(FqRepr([15168336788228049517, 6104148727050941414, 11744620724444176788, 291052430401786830, 12974234119515072997, 720310162563104718]))`,                                                                                         
 right: `Fq(FqRepr([962731235106226143, 16571648143052024727, 17135942836742034121, 4753685040599277843, 13337106476021869881, 8864284230283688178]))`', src/bls12_381/fq.rs:1817:4                                                            
note: Run with `RUST_BACKTRACE=1` for a backtrace. 

am I doing something wrong here?

There are two methods on Fq that you need to know about: from_repr which converts FqRepr into Fq elements, and from_str which converts a string into an Fq element.

Here's an example of from_str:

#[test]
fn just_testin() {
    assert_eq!(
        Fq::from_str(
            "1441654611304870083771668378362836059635368675687187728493436807246216518445765908198826216213302212825486491541923"
        ).unwrap().pow(&[9]),
        Fq::from_str(
            "2674805500308639681231231679735001911124329544452377898820909721146641766910845335783537874195940953433390291734292"
        ).unwrap()
    );
}

This is a quick-and-dirty python function for converting integers into the correct little-endian order for FqRepr:

def h(a):
    return hex(a % (2**64)) + ", " + hex((a >> 64) % (2**64)) + ", " + hex((a >> 128) % (2**64)) + ", " + hex((a >> 192) % (2**64))

However, it is (deliberately) not possible outside the library to construct Fq elements like you're doing here:

let e = Fq(FqRepr([0xd5bf6438391d2db, 0x9b472f83366efa4e, 0x6de01cbdb2717753,
                       0x6736fc8900b1e8da, 0xd86a603d9ce33eb7, 0x6243b9d40ce4d8c1]));

You need to use from_repr on Fq to do it, both because it could fail (when the representation is not in the field) and especially because the Fq element is internally represented in Montgomery form and needs to be converted into this form at runtime.

oh, neat, thanks a lot for the expensive explaination!
To set the record straight, I'm now using

def h(a): return ', '.join(hex((a >> (64*x)) % (2**64)) for x in range(6))

to do the job (obv. multiplying by R before to have it in Montgomery form, as you pointed out).