ed25519.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Based on
  3. * 1. OpenSSL lib
  4. * 2. PurpleI2P source code
  5. * 3. cppcodec lib
  6. *
  7. * PUBLIC DOMAIN C++ WRAPPER
  8. * acetone, 2022
  9. */
  10. #include "ed25519.h"
  11. #include "cppcodec/cppcodec/base64_default_rfc4648.hpp"
  12. #include <openssl/evp.h>
  13. namespace FriendlyCrypto {
  14. namespace Ed25519 {
  15. //// KeyPair
  16. void KeyPair::generateKeys() noexcept
  17. {
  18. EVP_PKEY_CTX * Ctx;
  19. EVP_PKEY * Pkey = nullptr;
  20. Ctx = EVP_PKEY_CTX_new_id (EVP_PKEY_ED25519, NULL);
  21. EVP_PKEY_keygen_init (Ctx);
  22. EVP_PKEY_keygen (Ctx, &Pkey);
  23. size_t len = 32;
  24. EVP_PKEY_get_raw_public_key (Pkey, m_public.data(), &len);
  25. EVP_PKEY_get_raw_private_key (Pkey, m_secret.data(), &len);
  26. EVP_PKEY_CTX_free (Ctx);
  27. EVP_PKEY_free (Pkey);
  28. }
  29. void KeyPair::setSecretKey (const std::array<uint8_t, 32> &secret) noexcept
  30. {
  31. m_secret = secret;
  32. EVP_PKEY * Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, m_secret.data(), 32);
  33. size_t len = 32;
  34. EVP_PKEY_get_raw_public_key (Pkey, m_public.data(), &len);
  35. EVP_PKEY_free (Pkey);
  36. }
  37. const std::array<uint8_t, 32> KeyPair::getSecretKey() const noexcept
  38. {
  39. return m_secret;
  40. }
  41. const std::array<uint8_t, 32> KeyPair::getPublicKey() const noexcept
  42. {
  43. return m_public;
  44. }
  45. const std::string KeyPair::getPublicKeyBase64String() const noexcept
  46. {
  47. return cppcodec::base64_rfc4648::encode (getPublicKey().data(), getPublicKey().size());
  48. }
  49. const std::string KeyPair::getSecretKeyBase64String() const noexcept
  50. {
  51. return cppcodec::base64_rfc4648::encode (getSecretKey().data(), getSecretKey().size());
  52. }
  53. //// Signature
  54. const std::shared_ptr<std::array<uint8_t, 64>> Signature::data() const noexcept
  55. {
  56. return m_data;
  57. }
  58. const std::string Signature::base64String() const noexcept
  59. {
  60. return cppcodec::base64_rfc4648::encode (m_data->data(), 64);
  61. }
  62. bool Signature::operator==(const Signature &another) const noexcept
  63. {
  64. return m_data == another.data();
  65. }
  66. bool Signature::operator==(const std::array<uint8_t, 64> &rawAnother) const noexcept
  67. {
  68. return *m_data == rawAnother;
  69. }
  70. bool Signature::operator==(const std::string &base64String) const noexcept
  71. {
  72. std::vector<uint8_t> anotherSignatureVector;
  73. try {
  74. anotherSignatureVector = cppcodec::base64_rfc4648::decode(base64String);
  75. } catch (...) {
  76. return false;
  77. }
  78. if (anotherSignatureVector.size() != 64)
  79. {
  80. return false;
  81. }
  82. std::array<uint8_t, 64> rawAnother;
  83. for (int i = 0; i < 64; ++i)
  84. {
  85. rawAnother[i] = anotherSignatureVector[i];
  86. }
  87. return operator==(rawAnother);
  88. }
  89. //// FUNCTIONS
  90. Ed25519::Signature sign (const std::vector<uint8_t> &message, const std::array<uint8_t, 32> &secretKey) noexcept
  91. {
  92. auto MDCtx = EVP_MD_CTX_create();
  93. auto PKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_ED25519, NULL, secretKey.data(), 32);
  94. EVP_DigestSignInit (MDCtx, NULL, NULL, NULL, PKey);
  95. size_t length = 64;
  96. std::array<uint8_t, 64> signature;
  97. EVP_DigestSign (MDCtx, signature.data(), &length, message.data(), message.size());
  98. EVP_PKEY_free (PKey);
  99. EVP_MD_CTX_destroy (MDCtx);
  100. return signature;
  101. }
  102. bool verify (const std::vector<uint8_t> &message, const Ed25519::Signature &signature, const std::array<uint8_t, 32> &publicKey) noexcept
  103. {
  104. auto MDCtx = EVP_MD_CTX_create();
  105. auto PKey = EVP_PKEY_new_raw_public_key (EVP_PKEY_ED25519, NULL, publicKey.data(), 32);
  106. EVP_DigestVerifyInit (MDCtx, NULL, NULL, NULL, PKey);
  107. bool res = EVP_DigestVerify (MDCtx, signature.data()->data(), 64, message.data(), message.size());
  108. EVP_PKEY_free (PKey);
  109. EVP_MD_CTX_destroy (MDCtx);
  110. return res;
  111. }
  112. } // namespace Ed25519
  113. } // namespace FriendlyCrypto