/ libi2pd / Signature.h
Signature.h
  1  /*
  2  * Copyright (c) 2013-2025, The PurpleI2P Project
  3  *
  4  * This file is part of Purple i2pd project and licensed under BSD3
  5  *
  6  * See full license text in LICENSE file at top of project tree
  7  */
  8  
  9  #ifndef SIGNATURE_H__
 10  #define SIGNATURE_H__
 11  
 12  #include <inttypes.h>
 13  #include <string.h>
 14  #include <openssl/dsa.h>
 15  #include <openssl/ec.h>
 16  #include <openssl/ecdsa.h>
 17  #include <openssl/evp.h>
 18  #include "Crypto.h"
 19  #include "Ed25519.h"
 20  #include "Gost.h"
 21  
 22  namespace i2p
 23  {
 24  namespace crypto
 25  {
 26  	class Verifier
 27  	{
 28  		public:
 29  
 30  			virtual ~Verifier () {};
 31  			virtual bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const = 0;
 32  			virtual size_t GetPublicKeyLen () const = 0;
 33  			virtual size_t GetSignatureLen () const = 0;
 34  			virtual size_t GetPrivateKeyLen () const { return GetSignatureLen ()/2; };
 35  			virtual void SetPublicKey (const uint8_t * signingKey) = 0;
 36  	};
 37  
 38  	class Signer
 39  	{
 40  		public:
 41  
 42  			virtual ~Signer () {};
 43  			virtual void Sign (const uint8_t * buf, int len, uint8_t * signature) const = 0;
 44  	};
 45  
 46  	// DSA
 47  	const size_t DSA_PUBLIC_KEY_LENGTH = 128;
 48  	const size_t DSA_SIGNATURE_LENGTH = 40;
 49  	const size_t DSA_PRIVATE_KEY_LENGTH = DSA_SIGNATURE_LENGTH/2;
 50  	class DSAVerifier: public Verifier
 51  	{
 52  		public:
 53  			
 54  			DSAVerifier ();
 55  			~DSAVerifier ();
 56  
 57  			// implements Verifier
 58  			void SetPublicKey (const uint8_t * signingKey) override;
 59  			bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const override;
 60  			size_t GetPublicKeyLen () const override { return DSA_PUBLIC_KEY_LENGTH; };
 61  			size_t GetSignatureLen () const override { return DSA_SIGNATURE_LENGTH; };
 62  			
 63  		private:
 64  
 65  #if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
 66  			EVP_PKEY * m_PublicKey;
 67  #else			
 68  			DSA * m_PublicKey;
 69  #endif			
 70  	};
 71  
 72  	class DSASigner: public Signer
 73  	{
 74  		public:
 75  
 76  			DSASigner (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey);
 77  			// openssl 1.1 always requires DSA public key even for signing
 78  			~DSASigner ();
 79  
 80  			// implements Signer
 81  			void Sign (const uint8_t * buf, int len, uint8_t * signature) const override;
 82  
 83  		private:
 84  
 85  #if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
 86  			EVP_PKEY * m_PrivateKey;
 87  #else
 88  			DSA * m_PrivateKey;
 89  #endif			
 90  	};
 91  
 92  	void CreateDSARandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey);
 93  
 94  	// ECDSA
 95  	constexpr size_t ECDSAP256_KEY_LENGTH = 64;
 96  	constexpr size_t ECDSAP384_KEY_LENGTH = 96;
 97  	constexpr size_t ECDSAP521_KEY_LENGTH = 132;
 98  	
 99  #if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
100  	class ECDSAVerifier: public Verifier
101  	{
102  		public:
103  
104  			ECDSAVerifier (int curve, size_t keyLen, const EVP_MD * hash);
105  			~ECDSAVerifier ();
106  		
107  			void SetPublicKey (const uint8_t * signingKey);
108  			bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
109  		
110  			size_t GetPublicKeyLen () const { return m_KeyLen; };
111  			size_t GetSignatureLen () const { return m_KeyLen; }; // signature length = key length
112  
113  		private:
114  
115  			int m_Curve;
116  			size_t m_KeyLen;
117  			const EVP_MD * m_Hash;
118  			EVP_PKEY * m_PublicKey;
119  	};		
120  
121  	class ECDSASigner: public Signer
122  	{
123  		public:
124  
125  			ECDSASigner (int curve, size_t keyLen, const EVP_MD * hash, const uint8_t * signingPrivateKey);
126  			~ECDSASigner ();
127  
128  			void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
129  			
130  		private:
131  
132  			size_t m_KeyLen;
133  			const EVP_MD * m_Hash;
134  			EVP_PKEY * m_PrivateKey;
135  	};			
136  	
137  	void CreateECDSARandomKeys (int curve, size_t keyLen, uint8_t * signingPrivateKey, uint8_t * signingPublicKey);
138  
139  // ECDSA_SHA256_P256	
140  	class ECDSAP256Verifier: public ECDSAVerifier
141  	{
142  		public:
143  			
144  			ECDSAP256Verifier (): ECDSAVerifier (NID_X9_62_prime256v1, ECDSAP256_KEY_LENGTH, EVP_sha256()) {};
145  	};	
146  
147  	class ECDSAP256Signer: public ECDSASigner
148  	{
149  		public:
150  
151  			ECDSAP256Signer (const uint8_t * signingPrivateKey):
152  				ECDSASigner (NID_X9_62_prime256v1, ECDSAP256_KEY_LENGTH, EVP_sha256(), signingPrivateKey) {};
153  	};	
154  	
155  	inline void CreateECDSAP256RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
156  	{
157  		CreateECDSARandomKeys (NID_X9_62_prime256v1, ECDSAP256_KEY_LENGTH, signingPrivateKey, signingPublicKey);
158  	}
159  
160  // ECDSA_SHA384_P384
161  	class ECDSAP384Verifier: public ECDSAVerifier
162  	{
163  		public:
164  			
165  			ECDSAP384Verifier (): ECDSAVerifier (NID_secp384r1, ECDSAP384_KEY_LENGTH, EVP_sha384()) {};
166  	};	
167  
168  	class ECDSAP384Signer: public ECDSASigner
169  	{
170  		public:
171  
172  			ECDSAP384Signer (const uint8_t * signingPrivateKey):
173  				ECDSASigner (NID_secp384r1, ECDSAP384_KEY_LENGTH, EVP_sha384(), signingPrivateKey) {};
174  	};	
175  	
176  	inline void CreateECDSAP384RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
177  	{
178  		CreateECDSARandomKeys (NID_secp384r1, ECDSAP384_KEY_LENGTH, signingPrivateKey, signingPublicKey);
179  	}
180  
181  // ECDSA_SHA512_P521
182  	class ECDSAP521Verifier: public ECDSAVerifier
183  	{
184  		public:
185  			
186  			ECDSAP521Verifier (): ECDSAVerifier (NID_secp521r1, ECDSAP521_KEY_LENGTH, EVP_sha512()) {};
187  	};	
188  
189  	class ECDSAP521Signer: public ECDSASigner
190  	{
191  		public:
192  
193  			ECDSAP521Signer (const uint8_t * signingPrivateKey):
194  				ECDSASigner (NID_secp521r1, ECDSAP521_KEY_LENGTH, EVP_sha512(), signingPrivateKey) {};
195  	};	
196  	
197  	inline void CreateECDSAP521RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
198  	{
199  		CreateECDSARandomKeys (NID_secp521r1, ECDSAP521_KEY_LENGTH, signingPrivateKey, signingPublicKey);
200  	}
201  	
202  #else
203  	
204  	struct SHA256Hash
205  	{
206  		static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest)
207  		{
208  			SHA256 (buf, len, digest);
209  		}
210  
211  		enum { hashLen = 32 };
212  	};
213  
214  	struct SHA384Hash
215  	{
216  		static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest)
217  		{
218  			SHA384 (buf, len, digest);
219  		}
220  
221  		enum { hashLen = 48 };
222  	};
223  
224  	struct SHA512Hash
225  	{
226  		static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest)
227  		{
228  			SHA512 (buf, len, digest);
229  		}
230  
231  		enum { hashLen = 64 };
232  	};
233  
234  	template<typename Hash, int curve, size_t keyLen>
235  	class ECDSAVerifier: public Verifier
236  	{
237  		public:
238  
239  			ECDSAVerifier ()
240  			{
241  				m_PublicKey = EC_KEY_new_by_curve_name (curve);
242  			}
243  
244  			void SetPublicKey (const uint8_t * signingKey)
245  			{
246  				BIGNUM * x = BN_bin2bn (signingKey, keyLen/2, NULL);
247  				BIGNUM * y = BN_bin2bn (signingKey + keyLen/2, keyLen/2, NULL);
248  				EC_KEY_set_public_key_affine_coordinates (m_PublicKey, x, y);
249  				BN_free (x); BN_free (y);
250  			}
251  
252  			~ECDSAVerifier ()
253  			{
254  				EC_KEY_free (m_PublicKey);
255  			}
256  
257  			bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
258  			{
259  				uint8_t digest[Hash::hashLen];
260  				Hash::CalculateHash (buf, len, digest);
261  				ECDSA_SIG * sig = ECDSA_SIG_new();
262  				auto r = BN_bin2bn (signature, GetSignatureLen ()/2, NULL);
263  				auto s = BN_bin2bn (signature + GetSignatureLen ()/2, GetSignatureLen ()/2, NULL);
264  				ECDSA_SIG_set0(sig, r, s);
265  				// ECDSA verification
266  				int ret = ECDSA_do_verify (digest, Hash::hashLen, sig, m_PublicKey) == 1;
267  				ECDSA_SIG_free(sig);
268  				return ret;
269  			}
270  
271  			size_t GetPublicKeyLen () const { return keyLen; };
272  			size_t GetSignatureLen () const { return keyLen; }; // signature length = key length
273  
274  
275  		private:
276  
277  			EC_KEY * m_PublicKey;
278  	};
279  
280  	template<typename Hash, int curve, size_t keyLen>
281  	class ECDSASigner: public Signer
282  	{
283  		public:
284  
285  			ECDSASigner (const uint8_t * signingPrivateKey)
286  			{
287  				m_PrivateKey = EC_KEY_new_by_curve_name (curve);
288  				EC_KEY_set_private_key (m_PrivateKey, BN_bin2bn (signingPrivateKey, keyLen/2, NULL));
289  			}
290  
291  			~ECDSASigner ()
292  			{
293  				EC_KEY_free (m_PrivateKey);
294  			}
295  
296  			void Sign (const uint8_t * buf, int len, uint8_t * signature) const
297  			{
298  				uint8_t digest[Hash::hashLen];
299  				Hash::CalculateHash (buf, len, digest);
300  				ECDSA_SIG * sig = ECDSA_do_sign (digest, Hash::hashLen, m_PrivateKey);
301  				const BIGNUM * r, * s;
302  				ECDSA_SIG_get0 (sig, &r, &s);
303  				// signatureLen = keyLen
304  				bn2buf (r, signature, keyLen/2);
305  				bn2buf (s, signature + keyLen/2, keyLen/2);
306  				ECDSA_SIG_free(sig);
307  			}
308  
309  		private:
310  
311  			EC_KEY * m_PrivateKey;
312  	};
313  
314  	inline void CreateECDSARandomKeys (int curve, size_t keyLen, uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
315  	{
316  		EC_KEY * signingKey = EC_KEY_new_by_curve_name (curve);
317  		EC_KEY_generate_key (signingKey);
318  		bn2buf (EC_KEY_get0_private_key (signingKey), signingPrivateKey, keyLen/2);
319  		BIGNUM * x = BN_new(), * y = BN_new();
320  		EC_POINT_get_affine_coordinates_GFp (EC_KEY_get0_group(signingKey),
321  			EC_KEY_get0_public_key (signingKey), x, y, NULL);
322  		bn2buf (x, signingPublicKey, keyLen/2);
323  		bn2buf (y, signingPublicKey + keyLen/2, keyLen/2);
324  		BN_free (x); BN_free (y);
325  		EC_KEY_free (signingKey);
326  	}
327  
328  // ECDSA_SHA256_P256
329  	typedef ECDSAVerifier<SHA256Hash, NID_X9_62_prime256v1, ECDSAP256_KEY_LENGTH> ECDSAP256Verifier;
330  	typedef ECDSASigner<SHA256Hash, NID_X9_62_prime256v1, ECDSAP256_KEY_LENGTH> ECDSAP256Signer;
331  
332  	inline void CreateECDSAP256RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
333  	{
334  		CreateECDSARandomKeys (NID_X9_62_prime256v1, ECDSAP256_KEY_LENGTH, signingPrivateKey, signingPublicKey);
335  	}
336  
337  // ECDSA_SHA384_P384
338  	typedef ECDSAVerifier<SHA384Hash, NID_secp384r1, ECDSAP384_KEY_LENGTH> ECDSAP384Verifier;
339  	typedef ECDSASigner<SHA384Hash, NID_secp384r1, ECDSAP384_KEY_LENGTH> ECDSAP384Signer;
340  
341  	inline void CreateECDSAP384RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
342  	{
343  		CreateECDSARandomKeys (NID_secp384r1, ECDSAP384_KEY_LENGTH, signingPrivateKey, signingPublicKey);
344  	}
345  
346  // ECDSA_SHA512_P521
347  	typedef ECDSAVerifier<SHA512Hash, NID_secp521r1, ECDSAP521_KEY_LENGTH> ECDSAP521Verifier;
348  	typedef ECDSASigner<SHA512Hash, NID_secp521r1, ECDSAP521_KEY_LENGTH> ECDSAP521Signer;
349  
350  	inline void CreateECDSAP521RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
351  	{
352  		CreateECDSARandomKeys (NID_secp521r1, ECDSAP521_KEY_LENGTH, signingPrivateKey, signingPublicKey);
353  	}
354  	
355  #endif
356  
357  	// EdDSA
358  	class EDDSA25519Verifier: public Verifier
359  	{
360  		public:
361  
362  			EDDSA25519Verifier ();
363  			void SetPublicKey (const uint8_t * signingKey);
364  			~EDDSA25519Verifier ();
365  
366  			bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
367  
368  			size_t GetPublicKeyLen () const { return EDDSA25519_PUBLIC_KEY_LENGTH; };
369  			size_t GetSignatureLen () const { return EDDSA25519_SIGNATURE_LENGTH; };
370  
371  		private:
372  			
373  			EVP_PKEY * m_Pkey;
374  			
375  		protected:
376  
377  			EVP_PKEY * GetPkey () const { return m_Pkey; };
378  	};
379  
380  #if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
381  	class EDDSA25519phVerifier: public EDDSA25519Verifier
382  	{
383  		public:
384  
385  			bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
386  	};
387  #endif	
388  	
389  	class EDDSA25519SignerCompat: public Signer
390  	{
391  		public:
392  
393  			EDDSA25519SignerCompat (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr);
394  			// we pass signingPublicKey to check if it matches private key
395  			~EDDSA25519SignerCompat ();
396  
397  			void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
398  			const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation
399  
400  		private:
401  
402  			uint8_t m_ExpandedPrivateKey[64];
403  			uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
404  	};
405  
406  	class EDDSA25519Signer: public Signer
407  	{
408  		public:
409  
410  			EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr);
411  			// we pass signingPublicKey to check if it matches private key
412  			~EDDSA25519Signer ();
413  
414  			void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
415  
416  		protected:
417  
418  			EVP_PKEY * GetPkey () const { return m_Pkey; };
419  			
420  		private:
421  
422  			EVP_PKEY * m_Pkey;
423  			EDDSA25519SignerCompat * m_Fallback;
424  	};
425  
426  #if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0
427  	class EDDSA25519phSigner: public EDDSA25519Signer
428  	{
429  		public:
430  
431  			EDDSA25519phSigner (const uint8_t * signingPrivateKey);
432  		
433  			void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
434  	};
435  	
436  #endif	
437  	
438  	inline void CreateEDDSA25519RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
439  	{
440  		EVP_PKEY *pkey = NULL;
441  		EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id (EVP_PKEY_ED25519, NULL);
442  		EVP_PKEY_keygen_init (pctx);
443  		EVP_PKEY_keygen (pctx, &pkey);
444  		EVP_PKEY_CTX_free (pctx);
445  		size_t len = EDDSA25519_PUBLIC_KEY_LENGTH;
446  		EVP_PKEY_get_raw_public_key (pkey, signingPublicKey, &len);
447  		len = EDDSA25519_PRIVATE_KEY_LENGTH;
448  		EVP_PKEY_get_raw_private_key (pkey, signingPrivateKey, &len);
449  		EVP_PKEY_free (pkey);
450  	}
451  
452  
453  	// ГОСТ Р 34.11
454  	struct GOSTR3411_256_Hash
455  	{
456  		static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest)
457  		{
458  			GOSTR3411_2012_256 (buf, len, digest);
459  		}
460  
461  		enum { hashLen = 32 };
462  	};
463  
464  	struct GOSTR3411_512_Hash
465  	{
466  		static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest)
467  		{
468  			GOSTR3411_2012_512 (buf, len, digest);
469  		}
470  
471  		enum { hashLen = 64 };
472  	};
473  
474  	// ГОСТ Р 34.10
475  	const size_t GOSTR3410_256_PUBLIC_KEY_LENGTH = 64;
476  	const size_t GOSTR3410_512_PUBLIC_KEY_LENGTH = 128;
477  
478  	template<typename Hash>
479  	class GOSTR3410Verifier: public Verifier
480  	{
481  		public:
482  
483  			enum { keyLen = Hash::hashLen };
484  
485  			GOSTR3410Verifier (GOSTR3410ParamSet paramSet):
486  				m_ParamSet (paramSet), m_PublicKey (nullptr)
487  			{
488  			}
489  
490  			void SetPublicKey (const uint8_t * signingKey)
491  			{
492  				BIGNUM * x = BN_bin2bn (signingKey, GetPublicKeyLen ()/2, NULL);
493  				BIGNUM * y = BN_bin2bn (signingKey + GetPublicKeyLen ()/2, GetPublicKeyLen ()/2, NULL);
494  				m_PublicKey = GetGOSTR3410Curve (m_ParamSet)->CreatePoint (x, y);
495  				BN_free (x); BN_free (y);
496  			}
497  			~GOSTR3410Verifier ()
498  			{
499  				if (m_PublicKey) EC_POINT_free (m_PublicKey);
500  			}
501  
502  			bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
503  			{
504  				uint8_t digest[Hash::hashLen];
505  				Hash::CalculateHash (buf, len, digest);
506  				BIGNUM * d = BN_bin2bn (digest, Hash::hashLen, nullptr);
507  				BIGNUM * r = BN_bin2bn (signature, GetSignatureLen ()/2, NULL);
508  				BIGNUM * s = BN_bin2bn (signature + GetSignatureLen ()/2, GetSignatureLen ()/2, NULL);
509  				bool ret = GetGOSTR3410Curve (m_ParamSet)->Verify (m_PublicKey, d, r, s);
510  				BN_free (d); BN_free (r); BN_free (s);
511  				return ret;
512  			}
513  
514  			size_t GetPublicKeyLen () const { return keyLen*2; }
515  			size_t GetSignatureLen () const { return keyLen*2; }
516  
517  		private:
518  
519  			GOSTR3410ParamSet m_ParamSet;
520  			EC_POINT * m_PublicKey;
521  	};
522  
523  	template<typename Hash>
524  	class GOSTR3410Signer: public Signer
525  	{
526  		public:
527  
528  			enum { keyLen = Hash::hashLen };
529  
530  			GOSTR3410Signer (GOSTR3410ParamSet paramSet, const uint8_t * signingPrivateKey):
531  				m_ParamSet (paramSet)
532  			{
533  				m_PrivateKey = BN_bin2bn (signingPrivateKey, keyLen, nullptr);
534  			}
535  			~GOSTR3410Signer () { BN_free (m_PrivateKey); }
536  
537  			void Sign (const uint8_t * buf, int len, uint8_t * signature) const
538  			{
539  				uint8_t digest[Hash::hashLen];
540  				Hash::CalculateHash (buf, len, digest);
541  				BIGNUM * d = BN_bin2bn (digest, Hash::hashLen, nullptr);
542  				BIGNUM * r = BN_new (), * s = BN_new ();
543  				GetGOSTR3410Curve (m_ParamSet)->Sign (m_PrivateKey, d, r, s);
544  				bn2buf (r, signature, keyLen);
545  				bn2buf (s, signature + keyLen, keyLen);
546  				BN_free (d); BN_free (r); BN_free (s);
547  			}
548  
549  		private:
550  
551  			GOSTR3410ParamSet m_ParamSet;
552  			BIGNUM * m_PrivateKey;
553  	};
554  
555  	inline void CreateGOSTR3410RandomKeys (GOSTR3410ParamSet paramSet, uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
556  	{
557  		const auto& curve = GetGOSTR3410Curve (paramSet);
558  		auto keyLen = curve->GetKeyLen ();
559  		RAND_bytes (signingPrivateKey, keyLen);
560  		BIGNUM * priv = BN_bin2bn (signingPrivateKey, keyLen, nullptr);
561  
562  		auto pub = curve->MulP (priv);
563  		BN_free (priv);
564  		BIGNUM * x = BN_new (), * y = BN_new ();
565  		curve->GetXY (pub, x, y);
566  		EC_POINT_free (pub);
567  		bn2buf (x, signingPublicKey, keyLen);
568  		bn2buf (y, signingPublicKey + keyLen, keyLen);
569  		BN_free (x); BN_free (y);
570  	}
571  
572  	typedef GOSTR3410Verifier<GOSTR3411_256_Hash> GOSTR3410_256_Verifier;
573  	typedef GOSTR3410Signer<GOSTR3411_256_Hash> GOSTR3410_256_Signer;
574  	typedef GOSTR3410Verifier<GOSTR3411_512_Hash> GOSTR3410_512_Verifier;
575  	typedef GOSTR3410Signer<GOSTR3411_512_Hash> GOSTR3410_512_Signer;
576  
577  	// RedDSA
578  	typedef EDDSA25519Verifier RedDSA25519Verifier;
579  	class RedDSA25519Signer: public Signer
580  	{
581  		public:
582  
583  			RedDSA25519Signer (const uint8_t * signingPrivateKey)
584  			{
585  				memcpy (m_PrivateKey, signingPrivateKey, EDDSA25519_PRIVATE_KEY_LENGTH);
586  				BN_CTX * ctx = BN_CTX_new ();
587  				auto publicKey = GetEd25519 ()->GeneratePublicKey (m_PrivateKey, ctx);
588  				GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx);
589  				BN_CTX_free (ctx);
590  			}
591  			~RedDSA25519Signer () {};
592  
593  			void Sign (const uint8_t * buf, int len, uint8_t * signature) const
594  			{
595  				GetEd25519 ()->SignRedDSA (m_PrivateKey, m_PublicKeyEncoded, buf, len, signature);
596  			}
597  
598  			const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation
599  
600  		private:
601  
602  			uint8_t m_PrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH];
603  			uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
604  	};
605  
606  	inline void CreateRedDSA25519RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
607  	{
608  		GetEd25519 ()->CreateRedDSAPrivateKey (signingPrivateKey);
609  		RedDSA25519Signer signer (signingPrivateKey);
610  		memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH);
611  	}
612  	
613  #if OPENSSL_PQ
614  #include <openssl/core_names.h>
615  	
616  	// Post-Quantum
617  	const size_t MLDSA44_PUBLIC_KEY_LENGTH = 1312;
618  	const size_t MLDSA44_SIGNATURE_LENGTH = 2420;
619  	const size_t MLDSA44_PRIVATE_KEY_LENGTH = 2560;
620  	class MLDSA44Verifier: public Verifier
621  	{
622  		public:
623  
624  			MLDSA44Verifier ();
625  			void SetPublicKey (const uint8_t * signingKey);
626  			~MLDSA44Verifier ();
627  
628  			bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const;
629  
630  			size_t GetPublicKeyLen () const { return MLDSA44_PUBLIC_KEY_LENGTH; };
631  			size_t GetSignatureLen () const { return MLDSA44_SIGNATURE_LENGTH; };
632  			size_t GetPrivateKeyLen () const { return MLDSA44_PRIVATE_KEY_LENGTH; };
633  
634  		private:
635  			
636  			EVP_PKEY * m_Pkey;
637  	};
638  
639  	class MLDSA44Signer: public Signer
640  	{
641  		public:
642  
643  			MLDSA44Signer (const uint8_t * signingPrivateKey);
644  			~MLDSA44Signer ();
645  
646  			void Sign (const uint8_t * buf, int len, uint8_t * signature) const;
647  			
648  		private:
649  
650  			EVP_PKEY * m_Pkey;
651  	};
652  	
653  	inline void CreateMLDSA44RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
654  	{
655  		EVP_PKEY * pkey = EVP_PKEY_Q_keygen (NULL, NULL, "ML-DSA-44");
656  		size_t len = MLDSA44_PUBLIC_KEY_LENGTH;
657          EVP_PKEY_get_octet_string_param (pkey, OSSL_PKEY_PARAM_PUB_KEY, signingPublicKey, MLDSA44_PUBLIC_KEY_LENGTH, &len);
658  		len = MLDSA44_PRIVATE_KEY_LENGTH;
659  		EVP_PKEY_get_octet_string_param (pkey, OSSL_PKEY_PARAM_PRIV_KEY, signingPrivateKey, MLDSA44_PRIVATE_KEY_LENGTH, &len);
660  		EVP_PKEY_free (pkey);
661  	}	
662  #endif	
663  }
664  }
665  
666  #endif