Intro To Cryptography - Chapter 6

Problem 6.2

Check that the points P=(1,4)P = (-1, 4) and Q=(2,5)Q = (2, 5) are points on the elliptic curve E:Y2=X3+17E: Y^2 = X^3 + 17.

Solution:

Y2=(4)2=16=(1)3+17=X3+17Y2=(5)2=25=(2)3+17=X3+17\begin{align*}Y^2 &= (4)^2 = 16 = (-1)^3 + 17 &= X^3 + 17 \\ Y^2 &= (5)^2 = 25 = (2)^3 + 17 &= X^3 + 17 \end{align*}

(a) Compute the points PQP \oplus Q and PQP \ominus Q.

Solution: Using Theorem 6.6:

PQ:λ=y2y1x2x2=542(1)=13x3=λ2x1x2=(13)2(1)2=89y3=λ(x1x3)y1=13(1(89))4=10927    PQ=(89,10927)\begin{align*} P\oplus Q :\qquad\qquad & \\ \lambda &= \frac{y_2 - y_1}{x_2 - x_2} = \frac{5-4}{2-(-1)} = \frac{1}{3} \\ x_3 &= \lambda^2 - x_1 - x_2 = \left(\frac{1}{3}\right)^2 - (-1) - 2 = \frac{-8}{9} \\ y_3 &= \lambda(x_1 - x_3) - y_1 = \frac{1}{3}\left(-1 - \left(\frac{-8}{9}\right)\right) - 4 = \frac{-109}{27} \\ \implies P \oplus Q &= \left(\frac{-8}{9}, \frac{-109}{27}\right)\end{align*}

To calculate PQP \ominus Q we use the same algorithm for \oplus, but with Q=(2,5)\ominus Q = (2, -5):

PQ:λ=y2y1x2x2=542(1)=93=3x3=λ2x1x2=(3)2(1)2=8y3=λ(x1x3)y1=3(18)4=23    PQ=(8,23)\begin{align*} P\ominus Q :\qquad\qquad & \\ \lambda &= \frac{y_2 - y_1}{x_2 - x_2} = \frac{-5-4}{2-(-1)} = \frac{-9}{3} = -3 \\ x_3 &= \lambda^2 - x_1 - x_2 = (-3)^2 - (-1) - 2 = 8 \\ y_3 &= \lambda(x_1 - x_3) - y_1 = -3\left(-1 - 8\right) - 4 = 23 \\ \implies P \ominus Q &= \left( 8, 23 \right)\end{align*}

(b) Compute the points 2P2P and 2Q2Q.

Solution:

2P:λ=3x12+A2y1=3(1)2+02(4)=38x3=λ2x1x2=(38)2(1)(1)=13764y3=λ(x1x3)y1=38(113764)4=2651512    2P=(13764,2651512)\begin{align*} 2P :\qquad\qquad & \\ \lambda &= \frac{3x_1^2 + A}{2y_1} = \frac{3(-1)^{2} + 0}{2(4)} = \frac{3}{8} \\ x_3 &= \lambda^2 - x_1 - x_2 = \left(\frac{3}{8}\right)^2 - (-1) - (-1) = \frac{137}{64} \\ y_3 &= \lambda(x_1 - x_3) - y_1 = \frac{3}{8}\left(-1 - \frac{137}{64}\right) - 4 = \frac{-2651}{512} \\ \implies 2P &= \left( \frac{137}{64}, \frac{-2651}{512} \right)\end{align*}

2Q:λ=3x12+A2y1=3(2)2+02(5)=65x3=λ2x1x2=(65)222=6425y3=λ(x1x3)y1=65(26425)5=59125    2Q=(6425,59125)\begin{align*} 2Q :\qquad\qquad & \\ \lambda &= \frac{3x_1^2 + A}{2y_1} = \frac{3(2)^{2} + 0}{2(5)} = \frac{6}{5} \\ x_3 &= \lambda^2 - x_1 - x_2 = \left(\frac{6}{5}\right)^2 - 2 - 2 = \frac{-64}{25} \\ y_3 &= \lambda(x_1 - x_3) - y_1 = \frac{6}{5}\left(2 - \frac{-64}{25}\right) - 5 = \frac{59}{125} \\ \implies 2Q &= \left( \frac{-64}{25}, \frac{59}{125} \right)\end{align*}

(bonus) How many points with integer coordinates can you find on EE?

Solution: Well, via enumeration we can find some smaller ones:

{(2,±3),(1,±4),(2,±5),(4,±9),(8,±23)} \{ (-2, \pm 3), (-1, \pm 4), (2, \pm 5), (4, \pm 9), (8, \pm 23) \}

It's clear from the equation for EE that there are no more negative values of XX that lie on EE. For finding more in the positive direction, I couldn't find a good analytic solution, so instead I brute forced it (see fn problem6_2 in the appendix) and found three additional points:

{(43,±282),(52,±375),(5234,±378661)} \{ (43, \pm 282), (52, \pm 375), (5234, \pm 378661) \}

Problem 6.5

For each of the following elliptic curves EE and finite fields Fp\mathbb{F}_p, make a list of the set of points E(Fp)E(\mathbb{F}_p).

(a) E:Y2=X3+3X+2E: Y^2 = X^3 + 3X + 2 over F7\mathbb{F}_7.

Solution: First writing out the list of squares in F7\mathbb{F}_7

{x2:xF7}={0,1,4,2,2,4,1}={0,1,2,4} \{ x^2 : x \in \mathbb{F}_7 \} = \{ 0, 1,4,2,2,4,1 \} = \{ 0,1,2,4 \}

we plug in all possible values into the RHS and keep those which match the squares, in addition to the special point at O\mathcal{O}:

{O,(0,3),(0,4),(2,3),(2,4),(4,1),(4,6),(5,3),(5,4)}\{ \mathcal{O}, (0, 3), (0, 4), (2, 3), (2, 4), (4, 1), (4, 6), (5, 3), (5, 4) \}

(b) E:Y2=X3+2X+7E: Y^2 = X^3 + 2X + 7 over F11\mathbb{F}_{11}.

Solution: Using the same approach,

{x2:xF11}={0,1,4,9,5,3,3,5,9,4,1}={0,1,3,4,5,9} \{ x^2 : x \in \mathbb{F}_{11} \} = \{ 0,1,4,9,5,3,3,5,9,4,1 \} = \{ 0,1,3,4,5,9 \}

Plugging in all possible values for XX, there's only two values 6,106, 10, that lead to perfect squares. So all the points on E(F11)E(\mathbb{F}_{11}) are:

{O,(6,2),(6,9),(7,1),(7,10),(10,2),(10,9)}\{ \mathcal{O}, (6, 2), (6, 9), (7, 1), (7, 10), (10, 2), (10, 9) \}

(c) E:Y2=X3+4X+5E: Y^2 = X^3 + 4X + 5 over F11\mathbb{F}_{11}.

Solution: Using the same strategy and the table of squares from part (b), we find the points on EE are

{O,(0,4),(0,7),(3,0),(6,5),(6,6),(9,0),(10,0)} \{ \mathcal{O}, (0, 4), (0, 7), (3, 0), (6, 5), (6, 6), (9, 0), (10, 0) \}

Problem 6.8

Let EE be the elliptic curve

E:y2=x3+x+1 E : y^2 = x^3 + x + 1

and let P=(4,2)P = (4,2 ) and Q=(0,1)Q = (0, 1) be points on EE modulo 55. Solve the elliptic curve discrete logarithm for PP and QQ. That is, find a positive integer nn such that Q=nPQ = nP.

Solution: Let's just enumerate nPnP:

2P=PP2P = P \oplus P:

λ=3x12+A2y1=3(4)2+14=44=1x3=λ2x1x2=1244=7=3y3=λ(x1x3)y1=(43)2=1=4    2P=(3,4)\begin{align*}\lambda &= \frac{3x_1^2 + A}{2y_1}= \frac{3(4)^2 + 1}{4} = \frac{4}{4} = 1 \\ x_3 &= \lambda^2 - x_1 - x_2 = 1^2 -4 -4 = -7 = 3 \\ y_3 &= \lambda(x_1 - x_3) - y_1 = (4- 3) - 2 = -1 = 4 \\ \implies 2P &= (3, 4) \end{align*}

3P=2PP3P = 2P \oplus P:

λ=y2y1x2x1=2443=2=3x3=λ2x1x2=3234=2y3=λ(x1x3)y1=3(32)4=1=4    3P=(2,4)\begin{align*}\lambda &= \frac{y_2 - y_1}{x_2 - x_1} = \frac{2-4}{4-3} = -2 = 3 \\ x_3 &= \lambda^2 - x_1 - x_2 = 3^2 -3 -4 = 2 \\ y_3 &= \lambda(x_1 - x_3) - y_1 = 3(3-2) - 4 = -1 = 4 \\ \implies 3P &= (2, 4) \end{align*}

4P=3PP4P = 3P \oplus P:

λ=y2y1x2x1=2442=1=4x3=λ2x1x2=4224=0y3=λ(x1x3)y1=4(20)4=4    4P=(0,4)\begin{align*}\lambda &= \frac{y_2 - y_1}{x_2 - x_1} = \frac{2-4}{4-2} = -1 = 4 \\ x_3 &= \lambda^2 - x_1 - x_2 = 4^2 -2 -4 = 0 \\ y_3 &= \lambda(x_1 - x_3) - y_1 = 4(2-0) - 4 = 4 \\ \implies 4P &= (0, 4) \end{align*}

Note that we have now found 4P=Q4P = \ominus Q, however we do not know the size of E(F5)E(\mathbb{F}_5) nor the order of PP, so we can't easily use this information to find nn. So let's continue:

5P=4PP5P = 4P \oplus P:

λ=y2y1x2x1=2440=34=12=2x3=λ2x1x2=2204=0y3=λ(x1x3)y1=2(00)4=1    5P=(0,1)\begin{align*}\lambda &= \frac{y_2 - y_1}{x_2 - x_1} = \frac{2-4}{4-0} = 3\cdot4 = 12 = 2 \\ x_3 &= \lambda^2 - x_1 - x_2 = 2^2 -0 -4 = 0 \\ y_3 &= \lambda(x_1 - x_3) - y_1 = 2(0-0) - 4 = 1 \\ \implies 5P &= (0, 1) \end{align*}

Therefore logP(Q)=5\log_P(Q) = 5.

Problem 6.14

Alice and Bob agree to use elliptic Diffie-Hellman key exchange with the prime, elliptic curve, and point:

p=2671,E:Y2=X3+171X+853,P=(1980,431)E(F2671)p = 2671, \quad E: Y^2 = X^3 + 171X + 853, \quad P = (1980, 431) \in E(\mathbb{F}_{2671})

(a) Alice sends Bob the point QA=(2110,543).Q_A = (2110, 543). Bob decides to use the secret multiplier nB=1943n_B = 1943. What point should Bob send to Alice?

Solution: Using the program in the appendix, I found

nBP=(1432,667). n_B P = (1432, 667).

(b) What is their secret shared value?

Solution: The shared value is

nBQA=(2424,911). n_B Q_A = (2424, 911).

(c) How difficult is it for Eve to figure out Alice's secret multiplier nAn_A? If you know how to program, use a computer to find nAn_A.

Solution: Since p is only 26712671, the size of E(Fq)E(\mathbb{F}_q) is not too large, so we can just exhaustively loop until we find a value of nn that works. Doing so yields nA=726n_A = 726.

(d) Alice and Bob decide to exchange a new piece of secret information using the same prime, curve, and point. This time Alice sends Bob only the xx-coordinate xA=2x_A = 2 of her point QAQ_A. Bob decides to use the secret multiplier nB=875n_B = 875. What single number modulo pp should Bob send to Alice, and what is their secret shared value?

Solution: Bob should send the number 161161 to Alice. Their secret shared value is 17081708.

Problem 6.16

A shortcoming of using an elliptic curve E(Fp)E(\mathbb{F}_p) for cryptography is the fact that it takes two coordinates to specify a point in E(Fp)E(\mathbb{F}_p). However, the second coordinate actually conveys very little additional information.

(a) Suppose that Bob wants to send Alice the value of a point RE(Fp)R \in E(\mathbb{F}_p). Explain why it suffices for Bob to send Alice the xx-coordinate of R=(xR,yR)R = (x_R, y_R) together with the single bit

βR={0 if 0yR<12p,1 if 12p<yR<p. \beta_R = \begin{cases} 0 & \text{ if } 0 \le y_R < \frac{1}{2}p, \\ 1 & \text{ if } \frac{1}{2}p < y_R < p. \end{cases}

(You may assume Alice is able to efficiently compute square roots modulo pp.)

Solution: The tuple (xR,βR)(x_R, \beta_R) is enough to identify the point (xR,yR)(x_R, y_R) on EE because there are only two points that share the same xx-coordinate: (xR,yR)(x_R, y_R) and (xR,yR)(x_R,-y_R ). Furthermore, in Fp\mathbb{F}_p we have

0y<12p    12p<y<p, 0 \le y < \frac{1}{2}p \quad \iff \quad \frac{1}{2}p < -y < p,

that is, we can say that those values less than 12p\frac{1}{2}p are the "positive" numbers and the ones greater than 12p\frac{1}{2}p are the "negative" numbers. This way, we only need one bit of information which informs which one of the two possible yy values (i.e. the positive or negative one) we want to convey. (Small note that we're assuming pp is some large prime, so it is odd, and we don't have to worry about equality on the 12p\frac{1}{2}p boundary.)

Thus, Alice simply needs to plug the xRx_R value into the equation for EE and she can find the value s=yR2s = y_R^2. After this she computes the square root (if p3mod  4p\equiv 3\mod4 then she can just compute s(p+1)/4mod  ps^{(p+1)/4}\mod p) to find ±yR\pm y_R. She then chooses the yy that satisfies the βR\beta_R condition.

(b) Alice and Bob decide to use the prime p=1123p = 1123 and the elliptic curve

E:Y2=X3+54X+87.E : Y^2 = X^3 + 54X + 87.

Bob sends Alice the xx-coordinate x=278x = 278 and the bit β=0\beta = 0. What point is Bob trying to convey to Alice? What about if instead Bob had sent β=1\beta = 1?

Solution: When β=0\beta = 0, Bob is trying to convey the point (278,487)(278, 487). When β=1\beta = 1, the point conveyed is (278,636)(278, 636).

Appendix

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Point {
    Coord(u64, u64),
    Zero,
}

pub struct Curve {
    pub p: u64,
    pub a: u64,
    pub b: u64,
    pub pk: Point,
}

impl Curve {
    /// Make an n multiple of a point, using the doulbe-and-add algorithm
    fn multiple(&self, n: u64, pt: Point) -> Point {
        let mut n = n;
        let mut q = pt;
        let mut r = Point::Zero;
        while n > 0 {
            if n % 2 == 1 {
                r = self.add(r, q);
            }
            q = self.add(q, q);
            n /= 2;
        }
        r
    }

    /// Add two points together
    fn add(&self, p1: Point, p2: Point) -> Point {
        match (p1, p2) {
            (Point::Zero, _) => p2,
            (_, Point::Zero) => p1,
            (Point::Coord(x1, y1), Point::Coord(x2, y2)) if x1 == x2 && y1 == self.neg(y2) => {
                Point::Zero
            }
            (Point::Coord(x1, y1), Point::Coord(x2, y2)) => {
                let lambda = if p1 != p2 {
                    (y2 + self.neg(y1)) * self.inv(x2 + self.neg(x1))
                } else {
                    (3 * (x1 * x1) + self.a) * self.inv(2 * y1)
                } % self.p;

                let x3 = ((lambda * lambda) + self.neg(x1) + self.neg(x2)) % self.p;
                let y3 = (lambda * (x1 + self.neg(x3)) + self.neg(y1)) % self.p;

                Point::Coord(x3, y3)
            }
        }
    }

    /// Return the "positive" y coordinate of E at the given x.
    fn eval_at(&self, x: u64) -> u64 {
        let y_sq = (x * x * x) + self.a * x + self.b % self.p;
        assert_eq!(
            self.p % 4,
            3,
            "this method does not work unless p = 3 mod 4"
        );
        mod_pow(y_sq, (self.p + 1) / 4, self.p)
    }

    /// Get additive inverse mod p.
    fn neg(&self, x: u64) -> u64 {
        (self.p - x) % self.p
    }

    /// Get multiplicative inverse mod p.
    fn inv(&self, x: u64) -> u64 {
        crate::fast_inv(x, self.p)
    }
}

fn mod_pow(base: u64, exp: u64, modulus: u64) -> u64 {
    let mut out = 1;
    for _ in 0..exp {
        out = out * base % modulus
    }
    out
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn example_6_16() {
        let curve = Curve {
            p: 3623,
            a: 14,
            b: 19,
            pk: Point::Coord(6, 730),
        };
        let n = 947;

        assert_eq!(curve.multiple(n, curve.pk), Point::Coord(3492, 60))
    }

    #[test]
    fn problem6_14_a() {
        let curve = Curve {
            p: 2671,
            a: 171,
            b: 853,
            pk: Point::Coord(1980, 431),
        };
        let n = 1943;

        assert_eq!(curve.multiple(n, curve.pk), Point::Coord(1432, 667))
    }

    #[test]
    fn problem6_14_b() {
        let curve = Curve {
            p: 2671,
            a: 171,
            b: 853,
            pk: Point::Coord(1980, 431),
        };
        let n = 1943;
        let q = Point::Coord(2110, 543);

        assert_eq!(curve.multiple(n, q), Point::Coord(2424, 911))
    }

    #[test]
    fn problem6_14_c() {
        let curve = Curve {
            p: 2671,
            a: 171,
            b: 853,
            pk: Point::Coord(1980, 431),
        };
        let q = Point::Coord(2110, 543);

        let n = (1..).find(|&n| curve.multiple(n, curve.pk) == q).unwrap();
        assert_eq!(n, 726);
    }

    #[test]
    fn problem6_14_d() {
        let curve = Curve {
            p: 2671,
            a: 171,
            b: 853,
            pk: Point::Coord(1980, 431),
        };

        let n = 875;
        let qb = curve.multiple(n, curve.pk);
        assert_eq!(qb, Point::Coord(161, 2040));

        let qx = 2;
        let qy = curve.eval_at(qx);
        let q = Point::Coord(qx, qy);
        let secret = curve.multiple(n, q);
        assert_eq!(secret, Point::Coord(1708, 1419));
    }

    #[test]
    fn problem6_16_b() {
        let curve = Curve {
            p: 1123,
            a: 54,
            b: 87,
            pk: Point::Zero,
        };

        let y_pos = curve.eval_at(278);
        assert_eq!(y_pos, 487);

        let y_neg = curve.p - y_pos;
        assert_eq!(y_neg, 636);
    }

    #[test]
    fn problem6_2() {
        let e = |x: u64| x.checked_pow(3).and_then(|x3| x3.checked_add(17));
        let mut sols = vec![];

        // For x > 0, y is increasing as a function of x, so once we find the
        // smallest x such that e(x) >= y^2, we can start the search for (y+1)^2
        // at e(x).
        let mut x: u64 = 0;
        // Ran with u64::MAX first, then replaced with the max y value found.
        for y in 1..=378661u64 {
            let ys = match y.checked_mul(y) {
                Some(ys) => ys,
                None => break,
            };
            while matches!(e(x), Some(e) if e < ys) {
                x += 1;
            }
            match e(x) {
                Some(e) if e == ys => {
                    sols.push((x, y));
                }
                None => break,
                _ => continue,
            }
        }
        assert_eq!(
            sols,
            vec![
                (2, 5),
                (4, 9),
                (8, 23),
                (43, 282),
                (52, 375),
                (5234, 378661)
            ]
        );
    }
}