# py_ecc

Warning

This library contains some experimental code and has not been audited.

## BLS Signatures

`py_ecc` implements the IETF BLS draft standard v4 as per the inter-blockchain standardization agreement. The BLS standards specify different ciphersuites which each have different functionality to accommodate various use cases. The following ciphersuites are available from this library:

- `G2Basic` also known as `BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_`

- `G2MessageAugmentation` also known as `BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_AUG_`

- `G2ProofOfPossession` also known as `BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_POP_`

## Basic Usage

    from py_ecc.bls import G2ProofOfPossession as bls_pop

    private_key = 5566
    public_key = bls_pop.SkToPk(private_key)

    message = b'\xab' * 32  # The message to be signed

    # Signing
    signature = bls_pop.Sign(private_key, message)

    # Verifying
    assert bls_pop.Verify(public_key, message, signature)

## Aggregating Signatures

    private_keys = [3, 14, 159]
    public_keys = [bls_pop.SkToPk(key) for key in private_keys]
    signatures = [bls_pop.Sign(key, message) for key in private_keys]

    # Aggregating
    agg_sig = bls_pop.Aggregate(signatures)

    # Verifying signatures over the same message.
    # Note this is only safe if Proofs of Possession have been verified for each of the public keys beforehand.
    # See the BLS standards for why this is the case.
    assert bls_pop.FastAggregateVerify(public_keys, message, agg_sig)

## Multiple Aggregation

    messages = [b'\xaa' * 42, b'\xbb' * 32, b'\xcc' * 64]
    signatures = [bls_pop.Sign(key, message) for key, message in zip(private_keys, messages)]
    agg_sig = bls_pop.Aggregate(signatures)

    # Verify aggregate signature with different messages
    assert bls_pop.AggregateVerify(public_keys, messages, agg_sig)

## py_ecc package

- py_ecc.bls package
  - Submodules
  - py_ecc.bls.ciphersuites module
    - `BaseG2Ciphersuite`
      - `BaseG2Ciphersuite.Aggregate()`
      - `BaseG2Ciphersuite.AggregateVerify()`
      - `BaseG2Ciphersuite.DST`
      - `BaseG2Ciphersuite.KeyGen()`
      - `BaseG2Ciphersuite.KeyValidate()`
      - `BaseG2Ciphersuite.Sign()`
      - `BaseG2Ciphersuite.SkToPk()`
      - `BaseG2Ciphersuite.Verify()`
      - `BaseG2Ciphersuite.xmd_hash_function()`
    - `G2Basic`
      - `G2Basic.AggregateVerify()`
      - `G2Basic.DST`
    - `G2MessageAugmentation`
      - `G2MessageAugmentation.AggregateVerify()`
      - `G2MessageAugmentation.DST`
      - `G2MessageAugmentation.Sign()`
      - `G2MessageAugmentation.Verify()`
    - `G2ProofOfPossession`
      - `G2ProofOfPossession.AggregateVerify()`
      - `G2ProofOfPossession.DST`
      - `G2ProofOfPossession.FastAggregateVerify()`
      - `G2ProofOfPossession.POP_TAG`
      - `G2ProofOfPossession.PopProve()`
      - `G2ProofOfPossession.PopVerify()`
  - py_ecc.bls.constants module
  - py_ecc.bls.g2_primitives module
    - `G1_to_pubkey()`
    - `G2_to_signature()`
    - `pubkey_to_G1()`
    - `signature_to_G2()`
    - `subgroup_check()`
  - py_ecc.bls.hash module
    - `expand_message_xmd()`
    - `hkdf_expand()`
    - `hkdf_extract()`
    - `i2osp()`
    - `os2ip()`
    - `sha256()`
    - `xor()`
  - py_ecc.bls.hash_to_curve module
    - `clear_cofactor_G1()`
    - `clear_cofactor_G2()`
    - `hash_to_G1()`
    - `hash_to_G2()`
    - `hash_to_field_FQ()`
    - `hash_to_field_FQ2()`
    - `map_to_curve_G1()`
    - `map_to_curve_G2()`
  - py_ecc.bls.point_compression module
    - `compress_G1()`
    - `compress_G2()`
    - `decompress_G1()`
    - `decompress_G2()`
    - `get_flags()`
    - `is_point_at_infinity()`
    - `modular_squareroot_in_FQ2()`
  - py_ecc.bls.typing module
  - Module contents
- py_ecc.bls12_381 package
  - Submodules
  - py_ecc.bls12_381.bls12_381_curve module
    - `add()`
    - `double()`
    - `eq()`
    - `is_inf()`
    - `is_on_curve()`
    - `multiply()`
    - `neg()`
    - `twist()`
  - py_ecc.bls12_381.bls12_381_pairing module
    - `cast_point_to_fq12()`
    - `final_exponentiate()`
    - `linefunc()`
    - `miller_loop()`
    - `pairing()`
  - Module contents
- py_ecc.bn128 package
  - Submodules
  - py_ecc.bn128.bn128_curve module
    - `add()`
    - `double()`
    - `eq()`
    - `is_inf()`
    - `is_on_curve()`
    - `multiply()`
    - `neg()`
    - `twist()`
  - py_ecc.bn128.bn128_pairing module
    - `cast_point_to_fq12()`
    - `final_exponentiate()`
    - `linefunc()`
    - `miller_loop()`
    - `pairing()`
  - Module contents
- py_ecc.optimized_bn128 package
  - Submodules
  - py_ecc.optimized_bn128.optimized_curve module
    - `add()`
    - `double()`
    - `eq()`
    - `is_inf()`
    - `is_on_curve()`
    - `multiply()`
    - `neg()`
    - `normalize()`
    - `twist()`
  - py_ecc.optimized_bn128.optimized_pairing module
    - `cast_point_to_fq12()`
    - `final_exponentiate()`
    - `linefunc()`
    - `miller_loop()`
    - `normalize1()`
    - `pairing()`
  - Module contents
- py_ecc.secp256k1 package
  - Submodules
  - py_ecc.secp256k1.secp256k1 module
    - `add()`
    - `bytes_to_int()`
    - `deterministic_generate_k()`
    - `ecdsa_raw_recover()`
    - `ecdsa_raw_sign()`
    - `from_jacobian()`
    - `inv()`
    - `jacobian_add()`
    - `jacobian_double()`
    - `jacobian_multiply()`
    - `multiply()`
    - `privtopub()`
    - `safe_ord()`
    - `to_jacobian()`
  - Module contents
- py_ecc.fields package
  - Submodules
  - py_ecc.fields.field_elements module
    - `FQ`
      - `FQ.field_modulus`
      - `FQ.n`
      - `FQ.one()`
      - `FQ.zero()`
    - `FQ12`
      - `FQ12.FQ12_MODULUS_COEFFS`
      - `FQ12.degree`
    - `FQ2`
      - `FQ2.FQ2_MODULUS_COEFFS`
      - `FQ2.degree`
    - `FQP`
      - `FQP.degree`
      - `FQP.field_modulus`
      - `FQP.inv()`
      - `FQP.one()`
      - `FQP.zero()`
  - py_ecc.fields.field_properties module
    - `Curve_Field_Properties`
      - `Curve_Field_Properties.field_modulus`
      - `Curve_Field_Properties.fq12_modulus_coeffs`
      - `Curve_Field_Properties.fq2_modulus_coeffs`
  - py_ecc.fields.optimized_field_elements module
    - `FQ`
      - `FQ.field_modulus`
      - `FQ.n`
      - `FQ.one()`
      - `FQ.sgn0`
      - `FQ.zero()`
    - `FQ12`
      - `FQ12.FQ12_MODULUS_COEFFS`
      - `FQ12.degree`
    - `FQ2`
      - `FQ2.FQ2_MODULUS_COEFFS`
      - `FQ2.degree`
      - `FQ2.sgn0`
    - `FQP`
      - `FQP.degree`
      - `FQP.field_modulus`
      - `FQP.inv()`
      - `FQP.mc_tuples`
      - `FQP.one()`
      - `FQP.optimized_poly_rounded_div()`
      - `FQP.sgn0`
      - `FQP.zero()`
    - `mod_int()`
  - Module contents
    - `bls12_381_FQ`
      - `bls12_381_FQ.field_modulus`
    - `bls12_381_FQ12`
      - `bls12_381_FQ12.FQ12_MODULUS_COEFFS`
      - `bls12_381_FQ12.field_modulus`
    - `bls12_381_FQ2`
      - `bls12_381_FQ2.FQ2_MODULUS_COEFFS`
      - `bls12_381_FQ2.field_modulus`
    - `bls12_381_FQP`
      - `bls12_381_FQP.field_modulus`
    - `bn128_FQ`
      - `bn128_FQ.field_modulus`
    - `bn128_FQ12`
      - `bn128_FQ12.FQ12_MODULUS_COEFFS`
      - `bn128_FQ12.field_modulus`
    - `bn128_FQ2`
      - `bn128_FQ2.FQ2_MODULUS_COEFFS`
      - `bn128_FQ2.field_modulus`
    - `bn128_FQP`
      - `bn128_FQP.field_modulus`
    - `optimized_bls12_381_FQ`
      - `optimized_bls12_381_FQ.field_modulus`
    - `optimized_bls12_381_FQ12`
      - `optimized_bls12_381_FQ12.FQ12_MODULUS_COEFFS`
      - `optimized_bls12_381_FQ12.field_modulus`
    - `optimized_bls12_381_FQ2`
      - `optimized_bls12_381_FQ2.FQ2_MODULUS_COEFFS`
      - `optimized_bls12_381_FQ2.field_modulus`
    - `optimized_bls12_381_FQP`
      - `optimized_bls12_381_FQP.field_modulus`
    - `optimized_bn128_FQ`
      - `optimized_bn128_FQ.field_modulus`
    - `optimized_bn128_FQ12`
      - `optimized_bn128_FQ12.FQ12_MODULUS_COEFFS`
      - `optimized_bn128_FQ12.field_modulus`
    - `optimized_bn128_FQ2`
      - `optimized_bn128_FQ2.FQ2_MODULUS_COEFFS`
      - `optimized_bn128_FQ2.field_modulus`
    - `optimized_bn128_FQP`
      - `optimized_bn128_FQP.field_modulus`
- py_ecc.optimized_bls12_381 package
  - Submodules
  - py_ecc.optimized_bls12_381.constants module
  - py_ecc.optimized_bls12_381.optimized_clear_cofactor module
    - `multiply_clear_cofactor_G1()`
    - `multiply_clear_cofactor_G2()`
  - py_ecc.optimized_bls12_381.optimized_curve module
    - `add()`
    - `double()`
    - `eq()`
    - `is_inf()`
    - `is_on_curve()`
    - `multiply()`
    - `neg()`
    - `normalize()`
    - `twist()`
  - py_ecc.optimized_bls12_381.optimized_pairing module
    - `cast_point_to_fq12()`
    - `exp_by_p()`
    - `final_exponentiate()`
    - `linefunc()`
    - `miller_loop()`
    - `normalize1()`
    - `pairing()`
  - py_ecc.optimized_bls12_381.optimized_swu module
    - `iso_map_G1()`
    - `iso_map_G2()`
    - `optimized_swu_G1()`
    - `optimized_swu_G2()`
    - `sqrt_division_FQ()`
    - `sqrt_division_FQ2()`
  - Module contents