diff options
Diffstat (limited to 'vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go')
-rw-r--r-- | vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go b/vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go new file mode 100644 index 00000000..a9bd7b48 --- /dev/null +++ b/vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go @@ -0,0 +1,97 @@ +package ecc + +// Package curve25519sign implements a signature scheme based on Curve25519 keys. +// See https://moderncrypto.org/mail-archive/curves/2014/000205.html for details. + +import ( + "crypto/ed25519" + "crypto/sha512" + + "filippo.io/edwards25519" + "filippo.io/edwards25519/field" +) + +// sign signs the message with privateKey and returns a signature as a byte slice. +func sign(privateKey *[32]byte, message []byte, random [64]byte) *[64]byte { + + // Calculate Ed25519 public key from Curve25519 private key + var A edwards25519.Point + privateKeyScalar, _ := edwards25519.NewScalar().SetBytesWithClamping(privateKey[:]) + A.ScalarBaseMult(privateKeyScalar) + publicKey := *(*[32]byte)(A.Bytes()) + + // Calculate r + diversifier := [32]byte{ + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + + var r [64]byte + hash := sha512.New() + hash.Write(diversifier[:]) + hash.Write(privateKey[:]) + hash.Write(message) + hash.Write(random[:]) + hash.Sum(r[:0]) + + // Calculate R + var rReduced *edwards25519.Scalar + rReduced, _ = edwards25519.NewScalar().SetUniformBytes(r[:]) + var R edwards25519.Point + R.ScalarBaseMult(rReduced) + + var encodedR [32]byte + encodedR = *(*[32]byte)(R.Bytes()) + + // Calculate S = r + SHA2-512(R || A_ed || msg) * a (mod L) + var hramDigest [64]byte + hash.Reset() + hash.Write(encodedR[:]) + hash.Write(publicKey[:]) + hash.Write(message) + hash.Sum(hramDigest[:0]) + hramDigestReduced, _ := edwards25519.NewScalar().SetUniformBytes(hramDigest[:]) + + sScalar := edwards25519.NewScalar().MultiplyAdd(hramDigestReduced, privateKeyScalar, rReduced) + s := *(*[32]byte)(sScalar.Bytes()) + + signature := new([64]byte) + copy(signature[:], encodedR[:]) + copy(signature[32:], s[:]) + signature[63] |= publicKey[31] & 0x80 + + return signature +} + +// verify checks whether the message has a valid signature. +func verify(publicKey [32]byte, message []byte, signature *[64]byte) bool { + + publicKey[31] &= 0x7F + + /* Convert the Curve25519 public key into an Ed25519 public key. In + particular, convert Curve25519's "montgomery" x-coordinate into an + Ed25519 "edwards" y-coordinate: + + ed_y = (mont_x - 1) / (mont_x + 1) + + NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp + + Then move the sign bit into the pubkey from the signature. + */ + + var edY, one, montX, montXMinusOne, montXPlusOne field.Element + _, _ = montX.SetBytes(publicKey[:]) + _ = one.One() + montXMinusOne.Subtract(&montX, &one) + montXPlusOne.Add(&montX, &one) + montXPlusOne.Invert(&montXPlusOne) + edY.Multiply(&montXMinusOne, &montXPlusOne) + + A_ed := *(*[32]byte)(edY.Bytes()) + + A_ed[31] |= signature[63] & 0x80 + signature[63] &= 0x7F + + return ed25519.Verify(A_ed[:], message, signature[:]) +} |