P-256 in Sage

This notebook demonstrates how to create a NIST P-256 curve ( aka secp256r1 ) and it's standard base point in Sagemath .

This blog post was originally written as a Sagemath notebook. The original notebook can be found here .

First, we define the parameters that make up the P-256 curve. The parameters are from “ SEC 2: Recommended Elliptic Curve Domain Parameters ".

# Finite field prime
p256 = 0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF

# Curve parameters for the curve equation: y^2 = x^3 + a256*x +b256
a256 = p256 - 3
b256 = 0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B

# Base point (x, y)
gx = 0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296
gy = 0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5

# Curve order

Then we can create a EllipticCurve sage object over a finite field.

# Create a finite field of order p256
FF = GF(p256)

# Define a curve over that field with specified Weierstrass a and b parameters
EC = EllipticCurve([FF(a256), FF(b256)])

# Since we know P-256's order we can skip computing it and set it explicitly

# Create a variable for the base point
G = EC(FF(gx), FF(gy))

We can compare results to a few public test vectors to make sure everything is working as intended.

These test vectors are defined as three-tuples: (scalar k, x-coordinate of k*G, y-coordinate of k*G)

test_vectors = [

for k, x, y in test_vectors:
    P = k*G
    Px, Py = P.xy()
    assert Px == x
    assert Py == y

That seems alright. We can do a simple ECDH to double check as well.

for _ in range(100):
    alice_private = randint(0, qq-1)
    alice_public = alice_private*G

    bob_private = randint(0, qq-1)
    bob_public = bob_private*G

    assert alice_private*bob_public == bob_private*alice_public
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

Notes on Virtualization.Framework

Authenticated Dictionaries with Skip Lists and Commutative Hashing