Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

math/big: Exp(x, x, x) returns x sometimes (instead of 0) #13907

Closed
rsc opened this issue Jan 11, 2016 · 2 comments
Closed

math/big: Exp(x, x, x) returns x sometimes (instead of 0) #13907

rsc opened this issue Jan 11, 2016 · 2 comments
Milestone

Comments

@rsc
Copy link
Contributor

rsc commented Jan 11, 2016

On #13515 (closed), @ysmolsky points out http://play.golang.org/p/QVWwgKMdCu.

That program sets:

x = 0xffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7edee386bfb5a899fa5ae9f24117c4b1fe649286651ece45b3dc2007cb8a163bf0598da48361c55d39a69163fa8fd24cf5f83655d23dca3ad961c62f356208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327ffffffffffffffff208552bb9ed529077096966d670c354e4abc9804f1746c08ca237327fffffffffffff

and then runs y.Exp(x, x, x) and finds that y == x instead of x == 0.

In fact much smaller numbers lead to the same result. The leading f's are important, because the Montgomery code works in a space where the answer is reduced to the bit length but not necessarily to the modulus. In some cases it appears that the final reduction is missed.

This program generates random cases that fail:

package main

import (
    "log"
    "math/big"
)

func main() {
    x := new(big.Int)
    y := new(big.Int)
    for size := 8; size < 64; size += 8 {
        bytes := make([]byte, size)
        for i := 0; i < size/2; i++ {
            bytes[i] = 0xFF
        }
        found := 0
        for loop := 0; ; {
            for i := size / 2; i < size; i++ {
                bytes[i] = byte(rand.Intn(256))
            }
            bytes[size-1] |= 1 // make it odd
            x.SetBytes(bytes)
            y.Exp(x, x, x)
            if y.BitLen() != 0 {
                if found == 0 {
                    log.Printf("#%d: %x => %x\n", loop, bytes, y)
                }
                found++
            }
            loop++
            if found > 0 && loop >= 1000 {
                log.Printf("size=%d found=%d/%d\n", size, found, loop)
                break
            }
            if loop >= 1<<20 {
                break
            }
        }
    }
}

In fact this program seems to show that every odd x with one word of leading f's has this problem. On 32-bit systems x = 0xffffffff00000001 and on 64-bit systems x = 0xffffffffffffffff0000000000000001 both exhibit the problem.

I will do the obvious thing and explicitly reduce the result.

/cc @vkrasnov

@rsc rsc self-assigned this Jan 11, 2016
@rsc rsc added this to the Go1.6 milestone Jan 11, 2016
@gopherbot
Copy link

CL https://golang.org/cl/18491 mentions this issue.

@gopherbot
Copy link

CL https://golang.org/cl/18586 mentions this issue.

gopherbot pushed a commit that referenced this issue Jan 13, 2016
Fixes #13907.

Change-Id: Ieaa5183f399b12a9177372212adf481c8f0b4a0d
Reviewed-on: https://go-review.googlesource.com/18491
Reviewed-by: Robert Griesemer <gri@golang.org>
Reviewed-by: Vlad Krasnov <vlad@cloudflare.com>
Reviewed-by: Adam Langley <agl@golang.org>
Reviewed-on: https://go-review.googlesource.com/18586
Reviewed-by: Chris Broadfoot <cbro@golang.org>
@golang golang locked and limited conversation to collaborators Jan 13, 2017
@rsc rsc removed their assignment Jun 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants