summaryrefslogtreecommitdiffstats
path: root/vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go')
-rw-r--r--vendor/go.mau.fi/libsignal/ecc/SignCurve25519.go97
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[:])
+}