use.std::math::secp256k1::base_field use.std::math::secp256k1::scalar_field use.std::math::secp256k1::group #! Given an ECDSA public key ( in projective coordinate system i.e. each secp256k1 curve point #! is represented in terms of X, Y, Z coordinates ), hashed message h ( a 256 -bit element represented #! in Montgomery form ) and an ECDSA signature, represented in terms of (r, s) s.t. each of them are #! represented in Montgomery form, this routine attempts to verify the ECDSA signature. #! #! Expected stack state #! #! [X, Y, Z, h, r, s, ...] i.e. total 48 elements on stack top #! #! X -> x0, x1, x2, x3, x4, x5, x6, x7 ( secp256k1 base field element, in Montgomery form ) #! Y -> y0, y1, y2, y3, y4, y5, y6, y7 ( secp256k1 base field element, in Montgomery form ) #! Z -> z0, z1, z2, z3, z4, z5, z6, z7 ( secp256k1 base field element, in Montgomery form ) #! h -> h0, h1, h2, h3, h4, h5, h6, h7 ( secp256k1 scalar field element, in Montgomery form ) #! r -> r0, r1, r2, r3, r4, r5, r6, r7 ( secp256k1 scalar field element, in Montgomery form ) #! s -> s0, s1, s2, s3, s4, s5, s6, s7 ( secp256k1 scalar field element, in Montgomery form ) #! #! Final stack state #! #! [ ... ] #! #! If verification fails, program execution will be aborted. #! #! See https://github.com/itzmeanjan/secp256k1/blob/37b339db3e03d24c2977399eb8896ef515ebb09b/ecdsa/verify.py#L11-L45 export.verify.24 # cache pub_key loc_storew.0 dropw loc_storew.1 dropw loc_storew.2 dropw loc_storew.3 dropw loc_storew.4 dropw loc_storew.5 dropw # cache h loc_storew.6 dropw loc_storew.7 dropw # cache r loc_storew.8 dropw loc_storew.9 dropw # Only s lives on stack # Invert s, over secp256k1 scalar field exec.scalar_field::inv dupw.1 dupw.1 # on stack [s^-1, s^-1, ...] push.0.0.0.0.0.0.0.0 # load h loc_loadw.7 swapw loc_loadw.6 # compute h * s^-1 exec.scalar_field::mul exec.scalar_field::from_mont # cache h * s^-1 loc_storew.6 swapw loc_storew.7 # load r loc_loadw.9 swapw loc_loadw.8 # compute r * s^-1 exec.scalar_field::mul exec.scalar_field::from_mont # cache r * s^-1 loc_storew.10 dropw loc_storew.11 dropw locaddr.17 locaddr.16 locaddr.15 locaddr.14 locaddr.13 locaddr.12 push.0.0.0.0.0.0.0.0 loc_loadw.7 swapw loc_loadw.6 # compute G * ((h * s^-1) mod N) = P0 exec.group::gen_mul push.0.0.0.0 movup.4 mem_loadw loc_storew.12 movup.4 mem_loadw loc_storew.13 movup.4 mem_loadw loc_storew.14 movup.4 mem_loadw loc_storew.15 movup.4 mem_loadw loc_storew.16 movup.4 mem_loadw loc_storew.17 dropw locaddr.23 locaddr.22 locaddr.21 locaddr.20 locaddr.19 locaddr.18 push.0.0.0.0.0.0.0.0 loc_loadw.11 swapw loc_loadw.10 locaddr.5 locaddr.4 locaddr.3 locaddr.2 locaddr.1 locaddr.0 # compute pkey * ((r * s^-1) mod N) = P1 exec.group::mul push.0.0.0.0 movup.4 mem_loadw loc_storew.0 movup.4 mem_loadw loc_storew.1 movup.4 mem_loadw loc_storew.2 movup.4 mem_loadw loc_storew.3 movup.4 mem_loadw loc_storew.4 movup.4 mem_loadw loc_storew.5 dropw locaddr.23 locaddr.22 locaddr.21 locaddr.20 locaddr.19 locaddr.18 locaddr.17 locaddr.16 locaddr.15 locaddr.14 locaddr.13 locaddr.12 locaddr.5 locaddr.4 locaddr.3 locaddr.2 locaddr.1 locaddr.0 # compute P0 + P1 = P2 exec.group::add push.0.0.0.0 movup.4 mem_loadw loc_storew.0 movup.4 mem_loadw loc_storew.1 movup.4 mem_loadw loc_storew.2 movup.4 mem_loadw loc_storew.3 movup.4 mem_loadw loc_storew.4 movup.4 mem_loadw loc_storew.5 push.0.0.0.0 loc_loadw.5 swapw loc_loadw.4 exec.base_field::inv push.0.0.0.0.0.0.0.0 loc_loadw.1 swapw loc_loadw.0 # compute r' ( in radix-2^32 form ) exec.base_field::mul exec.base_field::from_mont push.0.0.0.0.0.0.0.0 loc_loadw.9 swapw loc_loadw.8 # compute r ( in radix-2^32 form ) exec.scalar_field::from_mont # check if r == r' movup.8 assert_eq movup.7 assert_eq movup.6 assert_eq movup.5 assert_eq movup.4 assert_eq movup.3 assert_eq movup.2 assert_eq assert_eq end