Kaynağa Gözat

cleanup: moves from/to bytes conversion

From/to bytes conversion will be refactored when p503 is introduced.
Patch splits part that uses field specific functions from part that
converts Fp element to bytes.
Patch also removes some testing helpers which are no longer needed.
trials/PERF
Henry Case 6 yıl önce
committed by Kris Kwiatkowski
ebeveyn
işleme
1131231b8b
3 değiştirilmiş dosya ile 67 ekleme ve 108 silme
  1. +57
    -50
      p751toolbox/field.go
  2. +8
    -9
      p751toolbox/field_test.go
  3. +2
    -49
      p751toolbox/print_test.go

+ 57
- 50
p751toolbox/field.go Dosyayı Görüntüle

@@ -236,8 +236,20 @@ func (x *ExtensionFieldElement) ToBytes(output []byte) {
if len(output) < 188 {
panic("output byte slice too short, need 188 bytes")
}
x.A.toBytesFromMontgomeryForm(output[0:94])
x.B.toBytesFromMontgomeryForm(output[94:188])

var a,b Fp751Element
FromMontgomery(x, &a, &b)

// convert to bytes in little endian form. 8*12 = 96, but we drop the last two bytes
// since p is 751 < 752=94*8 bits.
for i := 0; i < 94; i++ {
// set i = j*8 + k
j := i / 8
k := uint64(i % 8)

output[i] = byte(a[j] >> (8 * k))
output[i+94] = byte(b[j] >> (8 * k))
}
}

// Read 188 bytes into the given ExtensionFieldElement.
@@ -247,8 +259,49 @@ func (x *ExtensionFieldElement) FromBytes(input []byte) {
if len(input) < 188 {
panic("input byte slice too short, need 188 bytes")
}
x.A.montgomeryFormFromBytes(input[:94])
x.B.montgomeryFormFromBytes(input[94:188])

for i:=0; i<94; i++ {
j := i / 8
k := uint64(i % 8)
x.A[j] |= uint64(input[i]) << (8 * k)
x.B[j] |= uint64(input[i+94]) << (8 * k)
}

ToMontgomery(x)
}

// Converts values in x.A and x.B to Montgomery domain
// x.A = x.A * R mod p
// x.B = x.B * R mod p
func ToMontgomery(x *ExtensionFieldElement) {
var aRR fp751X2

// convert to montgomery domain
fp751Mul(&aRR, &x.A, &montgomeryRsq) // = a*R*R
fp751MontgomeryReduce(&x.A, &aRR) // = a*R mod p
fp751Mul(&aRR, &x.B, &montgomeryRsq)
fp751MontgomeryReduce(&x.B, &aRR)
}

// Converts values in x.A and x.B from Montgomery domain
// a = x.A mod p
// b = x.B mod p
//
// After returning from the call x is not modified.
func FromMontgomery(x *ExtensionFieldElement, a,b *Fp751Element) {
var aR fp751X2

// convert from montgomery domain
copy(aR[:], x.A[:])
fp751MontgomeryReduce(a, &aR) // = a mod p in [0, 2p)
fp751StrongReduce(a) // = a mod p in [0, p)

for i:=range(aR) {
aR[i] = 0
}
copy(aR[:], x.B[:])
fp751MontgomeryReduce(b, &aR)
fp751StrongReduce(b)
}

//------------------------------------------------------------------------------
@@ -372,49 +425,3 @@ func (x Fp751Element) vartimeEq(y Fp751Element) bool {

return eq
}

// Read an Fp751Element from little-endian bytes and convert to Montgomery form.
//
// The input byte slice must be at least 94 bytes long.
func (x *Fp751Element) montgomeryFormFromBytes(input []byte) {
if len(input) < 94 {
panic("input byte slice too short")
}

var a Fp751Element
for i := 0; i < 94; i++ {
// set i = j*8 + k
j := i / 8
k := uint64(i % 8)
a[j] |= uint64(input[i]) << (8 * k)
}

var aRR fp751X2
fp751Mul(&aRR, &a, &montgomeryRsq) // = a*R*R
fp751MontgomeryReduce(x, &aRR) // = a*R mod p
}

// Given an Fp751Element in Montgomery form, convert to little-endian bytes.
//
// The output byte slice must be at least 94 bytes long.
func (x *Fp751Element) toBytesFromMontgomeryForm(output []byte) {
if len(output) < 94 {
panic("output byte slice too short")
}

var a Fp751Element
var aR fp751X2
copy(aR[:], x[:]) // = a*R
fp751MontgomeryReduce(&a, &aR) // = a mod p in [0, 2p)
fp751StrongReduce(&a) // = a mod p in [0, p)

// 8*12 = 96, but we drop the last two bytes since p is 751 < 752=94*8 bits.
for i := 0; i < 94; i++ {
// set i = j*8 + k
j := i / 8
k := uint64(i % 8)
// Need parens because Go's operator precedence would interpret
// a[j] >> 8*k as (a[j] >> 8) * k
output[i] = byte(a[j] >> (8 * k))
}
}

+ 8
- 9
p751toolbox/field_test.go Dosyayı Görüntüle

@@ -39,9 +39,9 @@ func VartimeEq(x,y *PrimeFieldElement) bool {
return x.A.vartimeEq(y.A)
}

func (x *PrimeFieldElement) toBigInt() *big.Int {
func (x *Fp751Element) toBigInt() *big.Int {
// Convert from Montgomery form
return x.A.toBigIntFromMontgomeryForm()
return x.toBigIntFromMontgomeryForm()
}

func (x *Fp751Element) toBigIntFromMontgomeryForm() *big.Int {
@@ -68,8 +68,8 @@ func TestPrimeFieldElementToBigInt(t *testing.T) {
// sage: assert(xR < 2*p)
// sage: (xR / R) % p
xBig, _ := new(big.Int).SetString("4469946751055876387821312289373600189787971305258234719850789711074696941114031433609871105823930699680637820852699269802003300352597419024286385747737509380032982821081644521634652750355306547718505685107272222083450567982240", 10)
if xBig.Cmp(x.toBigInt()) != 0 {
t.Error("Expected", xBig, "found", x.toBigInt())
if xBig.Cmp(x.A.toBigInt()) != 0 {
t.Error("Expected", xBig, "found", x.A.toBigInt())
}
}

@@ -125,7 +125,6 @@ func TestOneExtensionFieldToBytes(t *testing.T) {

x.One()
x.ToBytes(xBytes[:])

if xBytes[0] != 1 {
t.Error("Expected 1, got", xBytes[0])
}
@@ -259,10 +258,10 @@ func TestPrimeFieldElementMulVersusBigInt(t *testing.T) {
z.Mul(&x, &y)

check := new(big.Int)
check.Mul(x.toBigInt(), y.toBigInt())
check.Mul(x.A.toBigInt(), y.A.toBigInt())
check.Mod(check, cln16prime)

return check.Cmp(z.toBigInt()) == 0
return check.Cmp(z.A.toBigInt()) == 0
}

if err := quick.Check(mulMatchesBigInt, quickCheckConfig); err != nil {
@@ -276,10 +275,10 @@ func TestPrimeFieldElementP34VersusBigInt(t *testing.T) {
z := new(PrimeFieldElement)
z.P34(&x)

check := x.toBigInt()
check := x.A.toBigInt()
check.Exp(check, p34, cln16prime)

return check.Cmp(z.toBigInt()) == 0
return check.Cmp(z.A.toBigInt()) == 0
}

// This is more expensive; run fewer tests


+ 2
- 49
p751toolbox/print_test.go Dosyayı Görüntüle

@@ -3,64 +3,17 @@ package p751toolbox
// Tools used for testing and debugging

import (
"bytes"
"fmt"
)

func printHex(vector []byte) (out string) {
var buffer bytes.Buffer
buffer.WriteString("0x")
len := len(vector)
for i := len - 1; i >= 0; i-- {
buffer.WriteString(fmt.Sprintf("%02x", vector[i]))
}
buffer.WriteString("\n")
return buffer.String()
}

func (element Fp751Element) String() string {
var out [94]byte
element.toBytesFromMontgomeryForm(out[:])
return fmt.Sprintf("%s", printHex(out[:]))
}

func (primeElement PrimeFieldElement) String() string {
return fmt.Sprintf("%s", primeElement.A.String())
return fmt.Sprintf("%X", primeElement.A.toBigInt().String())
}

func (extElement ExtensionFieldElement) String() string {
var out [188]byte
extElement.ToBytes(out[:])
return fmt.Sprintf("A: %sB: %s", printHex(out[:94]), printHex(out[94:]))
return fmt.Sprintf("\nA: %X\nB: %X", extElement.A.toBigInt().String(), extElement.B.toBigInt().String())
}

func (point ProjectivePoint) String() string {
return fmt.Sprintf("X:\n%sZ:\n%s", point.X.String(), point.Z.String())
}

func (point Fp751Element) PrintHex() {
fmt.Printf("\t")
for i := 0; i < fp751NumWords/2; i++ {
fmt.Printf("0x%0.16X, ", point[i])
}
fmt.Printf("\n\t\t")
for i := fp751NumWords / 2; i < fp751NumWords; i++ {
fmt.Printf("0x%0.16X, ", point[i])
}
fmt.Printf("\n")
}

func (extElement ExtensionFieldElement) PrintHex() {
fmt.Printf("\t[r]: ")
extElement.A.PrintHex()
fmt.Printf("\t[u]: ")
extElement.B.PrintHex()
}

func (point ProjectivePoint) PrintHex() {
fmt.Printf("X:")
point.X.PrintHex()
fmt.Printf("Z:")
point.X.PrintHex()
fmt.Printf("\n")
}

Yükleniyor…
İptal
Kaydet