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.
 
 
 
 
 

421 lines
14 KiB

  1. /*
  2. * Example Decaf cyrpto routines, C++ wrapper.
  3. * @warning These are merely examples, though they ought to be secure. But real
  4. * protocols will decide differently on magic numbers, formats, which items to
  5. * hash, etc.
  6. * @warning Experimental! The names, parameter orders etc are likely to change.
  7. */
  8. #include <decaf/eddsa.hxx>
  9. #include <decaf/point_$(gf_bits).hxx>
  10. #include <decaf/ed$(gf_bits).h>
  11. #include <decaf/shake.hxx>
  12. #include <decaf/sha512.hxx>
  13. /** @cond internal */
  14. #if __cplusplus >= 201103L
  15. #define DECAF_NOEXCEPT noexcept
  16. #else
  17. #define DECAF_NOEXCEPT throw()
  18. #endif
  19. /** @endcond */
  20. /** Namespace for all libdecaf C++ objects. */
  21. namespace decaf {
  22. /** A public key for crypto over some Group */
  23. template <typename Group> struct EdDSA;
  24. /** A public key for crypto over $(name) */
  25. template<> struct EdDSA<$(cxx_ns)> {
  26. /** @cond internal */
  27. template<class CRTP, Prehashed> class Signing;
  28. template<class CRTP, Prehashed> class Verification;
  29. class PublicKeyBase;
  30. class PrivateKeyBase;
  31. typedef class PrivateKeyBase PrivateKey, PrivateKeyPure, PrivateKeyPh;
  32. typedef class PublicKeyBase PublicKey, PublicKeyPure, PublicKeyPh;
  33. /** @endcond */
  34. /**
  35. * Signatures support a "context" block, which allows you to domain separate them if
  36. * (for some reason) it's annoying to domain separate the message itself. The default
  37. * is no context. For Ed25519, the spec defining contexts is an extension, and the
  38. * default is not to use that extension. This makes "no context" different from
  39. * the empty string. For Ed448, contexts are built-in and mandatory, so "no context"
  40. * is the same as the empty string.
  41. */
  42. #if DECAF_EDDSA_$(gf_shortname)_SUPPORTS_CONTEXTLESS_SIGS
  43. static inline const Block NO_CONTEXT() { return Block(DECAF_ED$(gf_shortname)_NO_CONTEXT,0); }
  44. #else
  45. static inline const Block NO_CONTEXT() { return Block(NULL,0); }
  46. #endif
  47. /** Prehash context for EdDSA. */
  48. class Prehash : public $(re.sub(r"SHAKE(\d+)",r"SHAKE<\1>", eddsa_hash.upper())) {
  49. private:
  50. /** @cond internal */
  51. typedef $(re.sub(r"SHAKE(\d+)",r"SHAKE<\1>", eddsa_hash.upper())) Super;
  52. SecureBuffer context_;
  53. template<class T, Prehashed Ph> friend class Signing;
  54. template<class T, Prehashed Ph> friend class Verification;
  55. void init() /*throw(LengthException)*/ {
  56. Super::reset();
  57. if (context_.size() > 255) {
  58. throw LengthException();
  59. }
  60. decaf_ed$(gf_shortname)_prehash_init((decaf_$(eddsa_hash)_ctx_s *)wrapped);
  61. }
  62. /** @endcond */
  63. public:
  64. /** Number of output bytes in prehash */
  65. static const size_t OUTPUT_BYTES = Super::DEFAULT_OUTPUT_BYTES;
  66. /** Create the prehash */
  67. Prehash(const Block &context = NO_CONTEXT()) /*throw(LengthException)*/ {
  68. context_ = context;
  69. init();
  70. }
  71. /** Reset this hash */
  72. void reset() DECAF_NOEXCEPT { init(); }
  73. /** Output from this hash */
  74. SecureBuffer final() /*throw(std::bad_alloc)*/ {
  75. SecureBuffer ret = Super::final(OUTPUT_BYTES);
  76. reset();
  77. return ret;
  78. }
  79. /** Output from this hash */
  80. void final(Buffer &b) /*throw(LengthException)*/ {
  81. if (b.size() != OUTPUT_BYTES) throw LengthException();
  82. Super::final(b);
  83. reset();
  84. }
  85. };
  86. /** Signing (i.e. private) key class template */
  87. template<class CRTP, Prehashed ph> class Signing;
  88. /** Signing (i.e. private) key class, PureEdDSA version */
  89. template<class CRTP> class Signing<CRTP,PURE> {
  90. public:
  91. /**
  92. * Sign a message.
  93. * @param [in] message The message to be signed.
  94. * @param [in] context A context for the signature; must be at most 255 bytes.
  95. *
  96. * @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages.
  97. */
  98. inline SecureBuffer sign (
  99. const Block &message,
  100. const Block &context = NO_CONTEXT()
  101. ) const /* throw(LengthException, std::bad_alloc) */ {
  102. if (context.size() > 255) {
  103. throw LengthException();
  104. }
  105. SecureBuffer out(CRTP::SIG_BYTES);
  106. decaf_ed$(gf_shortname)_sign (
  107. out.data(),
  108. ((const CRTP*)this)->priv_.data(),
  109. ((const CRTP*)this)->pub_.data(),
  110. message.data(),
  111. message.size(),
  112. 0,
  113. context.data(),
  114. context.size()
  115. );
  116. return out;
  117. }
  118. };
  119. /** Signing (i.e. private) key class, prehashed version */
  120. template<class CRTP> class Signing<CRTP,PREHASHED> {
  121. public:
  122. /** Sign a prehash context, and reset the context */
  123. inline SecureBuffer sign_prehashed ( const Prehash &ph ) const /*throw(std::bad_alloc)*/ {
  124. SecureBuffer out(CRTP::SIG_BYTES);
  125. decaf_ed$(gf_shortname)_sign_prehash (
  126. out.data(),
  127. ((const CRTP*)this)->priv_.data(),
  128. ((const CRTP*)this)->pub_.data(),
  129. (const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped,
  130. ph.context_.data(),
  131. ph.context_.size()
  132. );
  133. return out;
  134. }
  135. /** Sign a message using the prehasher */
  136. inline SecureBuffer sign_with_prehash (
  137. const Block &message,
  138. const Block &context = NO_CONTEXT()
  139. ) const /*throw(LengthException,CryptoException)*/ {
  140. Prehash ph(context);
  141. ph += message;
  142. return sign_prehashed(ph);
  143. }
  144. };
  145. /** Signing (i.e. private) key base class */
  146. class PrivateKeyBase
  147. : public Serializable<PrivateKeyBase>
  148. , public Signing<PrivateKeyBase,PURE>
  149. , public Signing<PrivateKeyBase,PREHASHED> {
  150. public:
  151. /** Type of public key corresponding to this private key */
  152. typedef class PublicKeyBase PublicKey;
  153. private:
  154. /** @cond internal */
  155. friend class PublicKeyBase;
  156. friend class Signing<PrivateKey,PURE>;
  157. friend class Signing<PrivateKey,PREHASHED>;
  158. /** @endcond */
  159. /** The pre-expansion form of the signing key. */
  160. FixedArrayBuffer<DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES> priv_;
  161. /** The post-expansion public key. */
  162. FixedArrayBuffer<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> pub_;
  163. public:
  164. /** Underlying group */
  165. typedef $(cxx_ns) Group;
  166. /** Signature size. */
  167. static const size_t SIG_BYTES = DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES;
  168. /** Serialization size. */
  169. static const size_t SER_BYTES = DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES;
  170. /** Create but don't initialize */
  171. inline explicit PrivateKeyBase(const NOINIT&) DECAF_NOEXCEPT : priv_((NOINIT())), pub_((NOINIT())) { }
  172. /** Read a private key from a string */
  173. inline explicit PrivateKeyBase(const FixedBlock<SER_BYTES> &b) DECAF_NOEXCEPT { *this = b; }
  174. /** Copy constructor */
  175. inline PrivateKeyBase(const PrivateKey &k) DECAF_NOEXCEPT { *this = k; }
  176. /** Create at random */
  177. inline explicit PrivateKeyBase(Rng &r) DECAF_NOEXCEPT : priv_(r) {
  178. decaf_ed$(gf_shortname)_derive_public_key(pub_.data(), priv_.data());
  179. }
  180. /** Assignment from string */
  181. inline PrivateKeyBase &operator=(const FixedBlock<SER_BYTES> &b) DECAF_NOEXCEPT {
  182. memcpy(priv_.data(),b.data(),b.size());
  183. decaf_ed$(gf_shortname)_derive_public_key(pub_.data(), priv_.data());
  184. return *this;
  185. }
  186. /** Copy assignment */
  187. inline PrivateKeyBase &operator=(const PrivateKey &k) DECAF_NOEXCEPT {
  188. memcpy(priv_.data(),k.priv_.data(), priv_.size());
  189. memcpy(pub_.data(),k.pub_.data(), pub_.size());
  190. return *this;
  191. }
  192. /** Serialization size. */
  193. inline size_t ser_size() const DECAF_NOEXCEPT { return SER_BYTES; }
  194. /** Serialize into a buffer. */
  195. inline void serialize_into(unsigned char *x) const DECAF_NOEXCEPT {
  196. memcpy(x,priv_.data(), priv_.size());
  197. }
  198. /** Convert to X format (to be used for key exchange) */
  199. inline SecureBuffer convert_to_x() const {
  200. SecureBuffer out(DECAF_X$(gf_shortname)_PRIVATE_BYTES);
  201. decaf_ed$(gf_shortname)_convert_private_key_to_x$(gf_shortname)(out.data(), priv_.data());
  202. return out;
  203. }
  204. /** Return the corresponding public key */
  205. inline PublicKey pub() const DECAF_NOEXCEPT {
  206. PublicKey pub(*this);
  207. return pub;
  208. }
  209. }; /* class PrivateKey */
  210. /** Verification (i.e. public) EdDSA key, PureEdDSA version. */
  211. template<class CRTP> class Verification<CRTP,PURE> {
  212. public:
  213. /** Verify a signature, returning DECAF_FAILURE if verification fails */
  214. inline decaf_error_t DECAF_WARN_UNUSED verify_noexcept (
  215. const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig,
  216. const Block &message,
  217. const Block &context = NO_CONTEXT()
  218. ) const /*DECAF_NOEXCEPT*/ {
  219. if (context.size() > 255) {
  220. return DECAF_FAILURE;
  221. }
  222. return decaf_ed$(gf_shortname)_verify (
  223. sig.data(),
  224. ((const CRTP*)this)->pub_.data(),
  225. message.data(),
  226. message.size(),
  227. 0,
  228. context.data(),
  229. context.size()
  230. );
  231. }
  232. /** Verify a signature, throwing an exception if verification fails
  233. * @param [in] sig The signature.
  234. * @param [in] message The signed message.
  235. * @param [in] context A context for the signature; must be at most 255 bytes.
  236. *
  237. * @warning It is generally unsafe to use Ed25519 with both prehashed and non-prehashed messages.
  238. */
  239. inline void verify (
  240. const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig,
  241. const Block &message,
  242. const Block &context = NO_CONTEXT()
  243. ) const /*throw(LengthException,CryptoException)*/ {
  244. if (context.size() > 255) {
  245. throw LengthException();
  246. }
  247. if (DECAF_SUCCESS != verify_noexcept( sig, message, context )) {
  248. throw CryptoException();
  249. }
  250. }
  251. };
  252. /** Verification (i.e. public) EdDSA key, prehashed version. */
  253. template<class CRTP> class Verification<CRTP,PREHASHED> {
  254. public:
  255. /** Verify that a signature is valid for a given prehashed message, given the context. */
  256. inline decaf_error_t DECAF_WARN_UNUSED verify_prehashed_noexcept (
  257. const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig,
  258. const Prehash &ph
  259. ) const /*DECAF_NOEXCEPT*/ {
  260. return decaf_ed$(gf_shortname)_verify_prehash (
  261. sig.data(),
  262. ((const CRTP*)this)->pub_.data(),
  263. (const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped,
  264. ph.context_.data(),
  265. ph.context_.size()
  266. );
  267. }
  268. /** Verify that a signature is valid for a given prehashed message, given the context. */
  269. inline void verify_prehashed (
  270. const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig,
  271. const Prehash &ph
  272. ) const /*throw(CryptoException)*/ {
  273. if (DECAF_SUCCESS != decaf_ed$(gf_shortname)_verify_prehash (
  274. sig.data(),
  275. ((const CRTP*)this)->pub_.data(),
  276. (const decaf_ed$(gf_shortname)_prehash_ctx_s*)ph.wrapped,
  277. ph.context_.data(),
  278. ph.context_.size()
  279. )) {
  280. throw CryptoException();
  281. }
  282. }
  283. /** Hash and verify a message, using the prehashed verification mode. */
  284. inline void verify_with_prehash (
  285. const FixedBlock<DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES> &sig,
  286. const Block &message,
  287. const Block &context = NO_CONTEXT()
  288. ) const /*throw(LengthException,CryptoException)*/ {
  289. Prehash ph(context);
  290. ph += message;
  291. verify_prehashed(sig,ph);
  292. }
  293. };
  294. /** EdDSA Public key base class. */
  295. class PublicKeyBase
  296. : public Serializable<PublicKeyBase>
  297. , public Verification<PublicKeyBase,PURE>
  298. , public Verification<PublicKeyBase,PREHASHED> {
  299. public:
  300. /** Private key corresponding to this type of public key */
  301. typedef class PrivateKeyBase PrivateKey;
  302. private:
  303. /** @cond internal */
  304. friend class PrivateKeyBase;
  305. friend class Verification<PublicKey,PURE>;
  306. friend class Verification<PublicKey,PREHASHED>;
  307. private:
  308. /** The pre-expansion form of the signature */
  309. FixedArrayBuffer<DECAF_EDDSA_$(gf_shortname)_PUBLIC_BYTES> pub_;
  310. /** @endcond */
  311. public:
  312. /* PERF FUTURE: Pre-cached decoding? Precomputed table?? */
  313. /** Underlying group */
  314. typedef $(cxx_ns) Group;
  315. /** Signature size. */
  316. static const size_t SIG_BYTES = DECAF_EDDSA_$(gf_shortname)_SIGNATURE_BYTES;
  317. /** Serialization size. */
  318. static const size_t SER_BYTES = DECAF_EDDSA_$(gf_shortname)_PRIVATE_BYTES;
  319. /** Create but don't initialize */
  320. inline explicit PublicKeyBase(const NOINIT&) DECAF_NOEXCEPT : pub_((NOINIT())) { }
  321. /** Read a private key from a string */
  322. inline explicit PublicKeyBase(const FixedBlock<SER_BYTES> &b) DECAF_NOEXCEPT { *this = b; }
  323. /** Copy constructor */
  324. inline PublicKeyBase(const PublicKeyBase &k) DECAF_NOEXCEPT { *this = k; }
  325. /** Copy constructor */
  326. inline explicit PublicKeyBase(const PrivateKey &k) DECAF_NOEXCEPT { *this = k; }
  327. /** Assignment from string */
  328. inline PublicKey &operator=(const FixedBlock<SER_BYTES> &b) DECAF_NOEXCEPT {
  329. memcpy(pub_.data(),b.data(),b.size());
  330. return *this;
  331. }
  332. /** Assignment from private key */
  333. inline PublicKey &operator=(const PublicKey &p) DECAF_NOEXCEPT {
  334. return *this = p.pub_;
  335. }
  336. /** Assignment from private key */
  337. inline PublicKey &operator=(const PrivateKey &p) DECAF_NOEXCEPT {
  338. return *this = p.pub_;
  339. }
  340. /** Serialization size. */
  341. inline size_t ser_size() const DECAF_NOEXCEPT { return SER_BYTES; }
  342. /** Serialize into a buffer. */
  343. inline void serialize_into(unsigned char *x) const DECAF_NOEXCEPT {
  344. memcpy(x,pub_.data(), pub_.size());
  345. }
  346. /** Convert to X format (to be used for key exchange) */
  347. inline SecureBuffer convert_to_x() const {
  348. SecureBuffer out(DECAF_X$(gf_shortname)_PRIVATE_BYTES);
  349. decaf_ed$(gf_shortname)_convert_public_key_to_x$(gf_shortname)(out.data(), pub_.data());
  350. return out;
  351. }
  352. }; /* class PublicKey */
  353. }; /* template<> struct EdDSA<$(cxx_ns)> */
  354. #undef DECAF_NOEXCEPT
  355. } /* namespace decaf */