-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Edwards25519 and use always-square-and-multiply for pow, and fix …
…ristretto pow (#26) Signed-off-by: bytemare <3641580+bytemare@users.noreply.github.com>
- Loading branch information
Showing
18 changed files
with
1,335 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
// SPDX-License-Identifier: MIT | ||
// | ||
// Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved. | ||
// | ||
// This source code is licensed under the MIT license found in the | ||
// LICENSE file in the root directory of this source tree or at | ||
// https://spdx.org/licenses/MIT.html | ||
|
||
package edwards25519 | ||
|
||
import ( | ||
"fmt" | ||
|
||
ed "filippo.io/edwards25519" | ||
|
||
"github.com/bytemare/crypto/internal" | ||
) | ||
|
||
// Element implements the Element interface for the Ristretto255 group element. | ||
type Element struct { | ||
element ed.Point | ||
} | ||
|
||
func checkElement(element internal.Element) *Element { | ||
if element == nil { | ||
panic(internal.ErrParamNilPoint) | ||
} | ||
|
||
ec, ok := element.(*Element) | ||
if !ok { | ||
panic(internal.ErrCastElement) | ||
} | ||
|
||
return ec | ||
} | ||
|
||
// Base sets the element to the group's base point a.k.a. canonical generator. | ||
func (e *Element) Base() internal.Element { | ||
e.element.Set(ed.NewGeneratorPoint()) | ||
return e | ||
} | ||
|
||
// Identity sets the element to the point at infinity of the Group's underlying curve. | ||
func (e *Element) Identity() internal.Element { | ||
e.element.Set(ed.NewIdentityPoint()) | ||
return e | ||
} | ||
|
||
// Add sets the receiver to the sum of the input and the receiver, and returns the receiver. | ||
func (e *Element) Add(element internal.Element) internal.Element { | ||
ec := checkElement(element) | ||
e.element.Add(&e.element, &ec.element) | ||
|
||
return e | ||
} | ||
|
||
// Double sets the receiver to its double, and returns it. | ||
func (e *Element) Double() internal.Element { | ||
e.element.Add(&e.element, &e.element) | ||
return e | ||
} | ||
|
||
// Negate sets the receiver to its negation, and returns it. | ||
func (e *Element) Negate() internal.Element { | ||
e.element.Negate(&e.element) | ||
return e | ||
} | ||
|
||
// Subtract subtracts the input from the receiver, and returns the receiver. | ||
func (e *Element) Subtract(element internal.Element) internal.Element { | ||
ec := checkElement(element) | ||
e.element.Subtract(&e.element, &ec.element) | ||
|
||
return e | ||
} | ||
|
||
// Multiply sets the receiver to the scalar multiplication of the receiver with the given Scalar, and returns it. | ||
func (e *Element) Multiply(scalar internal.Scalar) internal.Element { | ||
if scalar == nil { | ||
e.Identity() | ||
return e | ||
} | ||
|
||
sc := assert(scalar) | ||
e.element.ScalarMult(&sc.scalar, &e.element) | ||
|
||
return e | ||
} | ||
|
||
// Equal returns 1 if the elements are equivalent, and 0 otherwise. | ||
func (e *Element) Equal(element internal.Element) int { | ||
ec := checkElement(element) | ||
return e.element.Equal(&ec.element) | ||
} | ||
|
||
// IsIdentity returns whether the Element is the point at infinity of the Group's underlying curve. | ||
func (e *Element) IsIdentity() bool { | ||
return e.element.Equal(ed.NewIdentityPoint()) == 1 | ||
} | ||
|
||
func (e *Element) set(element *Element) *Element { | ||
*e = *element | ||
return e | ||
} | ||
|
||
// Set sets the receiver to the value of the argument, and returns the receiver. | ||
func (e *Element) Set(element internal.Element) internal.Element { | ||
if element == nil { | ||
return e.set(nil) | ||
} | ||
|
||
ec, ok := element.(*Element) | ||
if !ok { | ||
panic(internal.ErrCastElement) | ||
} | ||
|
||
return e.set(ec) | ||
} | ||
|
||
// Copy returns a copy of the receiver. | ||
func (e *Element) Copy() internal.Element { | ||
return &Element{*ed.NewIdentityPoint().Set(&e.element)} | ||
} | ||
|
||
// Encode returns the compressed byte encoding of the element. | ||
func (e *Element) Encode() []byte { | ||
return e.element.Bytes() | ||
} | ||
|
||
// XCoordinate returns the encoded x coordinate of the element, which is the same as Encode(). | ||
func (e *Element) XCoordinate() []byte { | ||
return e.element.BytesMontgomery() | ||
} | ||
|
||
func decodeElement(element []byte) (*ed.Point, error) { | ||
if len(element) == 0 { | ||
return nil, internal.ErrParamNilPoint | ||
} | ||
|
||
e := ed.NewIdentityPoint() | ||
if _, err := e.SetBytes(element); err != nil { | ||
return nil, fmt.Errorf("edwards25519 element Decode: %w", err) | ||
} | ||
|
||
return e, nil | ||
} | ||
|
||
// Decode sets the receiver to a decoding of the input data, and returns an error on failure. | ||
func (e *Element) Decode(data []byte) error { | ||
element, err := decodeElement(data) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// superfluous identity check | ||
if element.Equal(ed.NewIdentityPoint()) == 1 { | ||
return internal.ErrIdentity | ||
} | ||
|
||
e.element = *element | ||
|
||
return nil | ||
} | ||
|
||
// MarshalBinary returns the compressed byte encoding of the element. | ||
func (e *Element) MarshalBinary() (data []byte, err error) { | ||
return e.Encode(), nil | ||
} | ||
|
||
// UnmarshalBinary sets e to the decoding of the byte encoded element. | ||
func (e *Element) UnmarshalBinary(data []byte) error { | ||
return e.Decode(data) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// SPDX-License-Identifier: MIT | ||
// | ||
// Copyright (C) 2021 Daniel Bourdrez. All Rights Reserved. | ||
// | ||
// This source code is licensed under the MIT license found in the | ||
// LICENSE file in the root directory of this source tree or at | ||
// https://spdx.org/licenses/MIT.html | ||
|
||
// Package edwards25519 allows simple and abstracted operations in the Edwards25519 group. | ||
package edwards25519 | ||
|
||
import ( | ||
ed "filippo.io/edwards25519" | ||
|
||
"github.com/bytemare/crypto/internal" | ||
) | ||
|
||
const ( | ||
canonicalEncodingLength = 32 | ||
orderPrime = "7237005577332262213973186563042994240857116359379907606001950938285454250989" | ||
) | ||
|
||
// Group represents the Edwards25519 group. It exposes a prime-order group API with hash-to-curve operations. | ||
type Group struct{} | ||
|
||
// New returns a new instantiation of the Edwards25519 Group. | ||
func New() internal.Group { | ||
return Group{} | ||
} | ||
|
||
// NewScalar returns a new, empty, scalar. | ||
func (g Group) NewScalar() internal.Scalar { | ||
return &Scalar{*ed.NewScalar()} | ||
} | ||
|
||
// NewElement returns the identity element (point at infinity). | ||
func (g Group) NewElement() internal.Element { | ||
return &Element{*ed.NewIdentityPoint()} | ||
} | ||
|
||
// Base returns group's base point a.k.a. canonical generator. | ||
func (g Group) Base() internal.Element { | ||
return &Element{*ed.NewGeneratorPoint()} | ||
} | ||
|
||
// HashToScalar returns a safe mapping of the arbitrary input to a Scalar. | ||
// The DST must not be empty or nil, and is recommended to be longer than 16 bytes. | ||
func (g Group) HashToScalar(input, dst []byte) internal.Scalar { | ||
return &Scalar{*HashToEdwards25519Field(input, dst)} | ||
} | ||
|
||
// HashToGroup returns a safe mapping of the arbitrary input to an Element in the Group. | ||
// The DST must not be empty or nil, and is recommended to be longer than 16 bytes. | ||
func (g Group) HashToGroup(input, dst []byte) internal.Element { | ||
return &Element{*HashToEdwards25519(input, dst)} | ||
} | ||
|
||
// EncodeToGroup returns a non-uniform mapping of the arbitrary input to an Element in the Group. | ||
// The DST must not be empty or nil, and is recommended to be longer than 16 bytes. | ||
func (g Group) EncodeToGroup(input, dst []byte) internal.Element { | ||
return &Element{*EncodeToEdwards25519(input, dst)} | ||
} | ||
|
||
// Ciphersuite returns the hash-to-curve ciphersuite identifier. | ||
func (g Group) Ciphersuite() string { | ||
return H2C | ||
} | ||
|
||
// ScalarLength returns the byte size of an encoded element. | ||
func (g Group) ScalarLength() uint { | ||
return canonicalEncodingLength | ||
} | ||
|
||
// ElementLength returns the byte size of an encoded element. | ||
func (g Group) ElementLength() uint { | ||
return canonicalEncodingLength | ||
} | ||
|
||
// Order returns the order of the canonical group of scalars. | ||
func (g Group) Order() string { | ||
return orderPrime | ||
} |
Oops, something went wrong.