Kaynağa Gözat

cleanup: move from/to bytes conversion to single function

From/to bytes conversion is needed only in ExtensionFieldElement. Patch
moves all conversion code to single place.
Patch also removes some testing helpers which are no longer needed.
trials/prep_p503_trial4
Henry Case 6 yıl önce
ebeveyn
işleme
b4df092ecd
3 değiştirilmiş dosya ile 45 ekleme ve 108 silme
  1. +35
    -50
      p751toolbox/field.go
  2. +8
    -9
      p751toolbox/field_test.go
  3. +2
    -49
      p751toolbox/print_test.go

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

@@ -236,8 +236,27 @@ 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
var aR fp751X2

// convert from montgomery domain
copy(aR[:], x.A[:]) // = a*R
fp751MontgomeryReduce(&a, &aR) // = a mod p in [0, 2p)
fp751StrongReduce(&a) // = a mod p in [0, p)
copy(aR[:], x.B[:])
fp751MontgomeryReduce(&b, &aR)
fp751StrongReduce(&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 +266,20 @@ 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)
}

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

//------------------------------------------------------------------------------
@@ -372,49 +403,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