You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ed25519.go 2.5KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. package atto
  2. import (
  3. "math/big"
  4. "filippo.io/edwards25519"
  5. "golang.org/x/crypto/blake2b"
  6. )
  7. func sign(publicKey, privateKey *big.Int, msg []byte) ([]byte, error) {
  8. // This implementation based on the one from github.com/iotaledger/iota.go.
  9. signature := make([]byte, 64, 64)
  10. h, err := blake2b.New512(nil)
  11. if err != nil {
  12. return signature, err
  13. }
  14. h.Write(bigIntToBytes(privateKey, 32))
  15. var digest1, messageDigest, hramDigest [64]byte
  16. h.Sum(digest1[:0])
  17. s := new(edwards25519.Scalar).SetBytesWithClamping(digest1[:32])
  18. h.Reset()
  19. h.Write(digest1[32:])
  20. h.Write(msg)
  21. h.Sum(messageDigest[:0])
  22. rReduced := new(edwards25519.Scalar).SetUniformBytes(messageDigest[:])
  23. R := new(edwards25519.Point).ScalarBaseMult(rReduced)
  24. encodedR := R.Bytes()
  25. h.Reset()
  26. h.Write(encodedR[:])
  27. h.Write(bigIntToBytes(publicKey, 32))
  28. h.Write(msg)
  29. h.Sum(hramDigest[:0])
  30. kReduced := new(edwards25519.Scalar).SetUniformBytes(hramDigest[:])
  31. S := new(edwards25519.Scalar).MultiplyAdd(kReduced, s, rReduced)
  32. copy(signature[:], encodedR[:])
  33. copy(signature[32:], S.Bytes())
  34. return signature, nil
  35. }
  36. func isValidSignature(publicKey *big.Int, msg, sig []byte) bool {
  37. // This implementation based on the one from github.com/iotaledger/iota.go.
  38. publicKeyBytes := bigIntToBytes(publicKey, 32)
  39. // ZIP215: this works because SetBytes does not check that encodings are canonical
  40. A, err := new(edwards25519.Point).SetBytes(publicKeyBytes)
  41. if err != nil {
  42. return false
  43. }
  44. A.Negate(A)
  45. h, err := blake2b.New512(nil)
  46. if err != nil {
  47. return false
  48. }
  49. h.Write(sig[:32])
  50. h.Write(publicKeyBytes)
  51. h.Write(msg)
  52. var digest [64]byte
  53. h.Sum(digest[:0])
  54. hReduced := new(edwards25519.Scalar).SetUniformBytes(digest[:])
  55. // ZIP215: this works because SetBytes does not check that encodings are canonical
  56. checkR, err := new(edwards25519.Point).SetBytes(sig[:32])
  57. if err != nil {
  58. return false
  59. }
  60. // https://tools.ietf.org/html/rfc8032#section-5.1.7 requires that s be in
  61. // the range [0, order) in order to prevent signature malleability
  62. s, err := new(edwards25519.Scalar).SetCanonicalBytes(sig[32:])
  63. if err != nil {
  64. return false
  65. }
  66. R := new(edwards25519.Point).VarTimeDoubleScalarBaseMult(hReduced, A, s)
  67. // ZIP215: We want to check [8](R - checkR) == 0
  68. p := new(edwards25519.Point).Subtract(R, checkR) // p = R - checkR
  69. p.Add(p, p) // p = [2]p
  70. p.Add(p, p) // p = [4]p
  71. p.Add(p, p) // p = [8]p
  72. return p.Equal(edwards25519.NewIdentityPoint()) == 1 // p == 0
  73. }