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.

121 lines
3.0 KiB

  1. package paillier
  2. import (
  3. "crypto/rand"
  4. "errors"
  5. "math/big"
  6. // prime "../prime"
  7. "github.com/arnaucube/cryptofun/prime"
  8. )
  9. const (
  10. bits = 16
  11. )
  12. // PublicKey stores the public key data
  13. type PublicKey struct {
  14. N *big.Int `json:"n"`
  15. G *big.Int `json:"g"`
  16. }
  17. // PrivateKey stores the private key data
  18. type PrivateKey struct {
  19. Lambda *big.Int `json:"lambda"`
  20. Mu *big.Int `json:"mu"`
  21. }
  22. // Key stores the public and private key data
  23. type Key struct {
  24. PubK PublicKey
  25. PrivK PrivateKey
  26. }
  27. // GenerateKeyPair generates a random private and public key
  28. func GenerateKeyPair() (key Key, err error) {
  29. p, err := rand.Prime(rand.Reader, bits/2)
  30. if err != nil {
  31. return key, err
  32. }
  33. q, err := rand.Prime(rand.Reader, bits/2)
  34. if err != nil {
  35. return key, err
  36. }
  37. pq := new(big.Int).Mul(p, q)
  38. p1q1 := big.NewInt((p.Int64() - 1) * (q.Int64() - 1))
  39. gcd := new(big.Int).GCD(nil, nil, pq, p1q1)
  40. if gcd.Int64() != int64(1) {
  41. return key, errors.New("gcd comprovation failed")
  42. }
  43. n := new(big.Int).Mul(p, q)
  44. lambda := big.NewInt(int64(lcm(float64(p.Int64())-1, float64(q.Int64())-1)))
  45. //g generation
  46. alpha := big.NewInt(int64(prime.RandInt(0, int(n.Int64()))))
  47. beta := big.NewInt(int64(prime.RandInt(0, int(n.Int64()))))
  48. alphan := new(big.Int).Mul(alpha, n)
  49. alphan1 := new(big.Int).Add(alphan, big.NewInt(1))
  50. betaN := new(big.Int).Exp(beta, n, nil)
  51. ab := new(big.Int).Mul(alphan1, betaN)
  52. n2 := new(big.Int).Mul(n, n)
  53. g := new(big.Int).Mod(ab, n2)
  54. //in some Paillier implementations use this:
  55. // g = new(big.Int).Add(n, big.NewInt(1))
  56. key.PubK.N = n
  57. key.PubK.G = g
  58. //mu generation
  59. Glambda := new(big.Int).Exp(g, lambda, nil)
  60. u := new(big.Int).Mod(Glambda, n2)
  61. L := l(u, n)
  62. mu := new(big.Int).ModInverse(L, n)
  63. key.PrivK.Lambda = lambda
  64. key.PrivK.Mu = mu
  65. return key, nil
  66. }
  67. func lcm(a, b float64) float64 {
  68. r := (a * b) / float64(prime.Gcd(int(a), int(b)))
  69. return r
  70. }
  71. func l(u *big.Int, n *big.Int) *big.Int {
  72. u1 := new(big.Int).Sub(u, big.NewInt(1))
  73. L := new(big.Int).Div(u1, n)
  74. return L
  75. }
  76. // Encrypt encrypts a message m with given PublicKey
  77. func Encrypt(m *big.Int, pubK PublicKey) *big.Int {
  78. gM := new(big.Int).Exp(pubK.G, m, nil)
  79. r := big.NewInt(int64(prime.RandInt(0, int(pubK.N.Int64()))))
  80. rN := new(big.Int).Exp(r, pubK.N, nil)
  81. gMrN := new(big.Int).Mul(gM, rN)
  82. n2 := new(big.Int).Mul(pubK.N, pubK.N)
  83. c := new(big.Int).Mod(gMrN, n2)
  84. return c
  85. }
  86. // Decrypt deencrypts a ciphertext c with given PublicKey and PrivateKey
  87. func Decrypt(c *big.Int, pubK PublicKey, privK PrivateKey) *big.Int {
  88. cLambda := new(big.Int).Exp(c, privK.Lambda, nil)
  89. n2 := new(big.Int).Mul(pubK.N, pubK.N)
  90. u := new(big.Int).Mod(cLambda, n2)
  91. L := l(u, pubK.N)
  92. LMu := new(big.Int).Mul(L, privK.Mu)
  93. m := new(big.Int).Mod(LMu, pubK.N)
  94. return m
  95. }
  96. // HomomorphicAddition calculates the addition of tow encrypted values given a PublicKey
  97. func HomomorphicAddition(c1 *big.Int, c2 *big.Int, pubK PublicKey) *big.Int {
  98. c1c2 := new(big.Int).Mul(c1, c2)
  99. n2 := new(big.Int).Mul(pubK.N, pubK.N)
  100. d := new(big.Int).Mod(c1c2, n2)
  101. return d
  102. }