mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-22 21:37:17 +01:00
complete implementation of RedDSA
This commit is contained in:
parent
c797ac4268
commit
ff44bcc489
|
@ -121,8 +121,8 @@ namespace crypto
|
||||||
return passed;
|
return passed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ed25519::Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len,
|
void Ed25519::Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded,
|
||||||
uint8_t * signature) const
|
const uint8_t * buf, size_t len, uint8_t * signature) const
|
||||||
{
|
{
|
||||||
BN_CTX * bnCtx = BN_CTX_new ();
|
BN_CTX * bnCtx = BN_CTX_new ();
|
||||||
// calculate r
|
// calculate r
|
||||||
|
@ -153,6 +153,44 @@ namespace crypto
|
||||||
BN_CTX_free (bnCtx);
|
BN_CTX_free (bnCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ed25519::SignRedDSA (const uint8_t * privateKey, const uint8_t * publicKeyEncoded,
|
||||||
|
const uint8_t * buf, size_t len, uint8_t * signature) const
|
||||||
|
{
|
||||||
|
BN_CTX * bnCtx = BN_CTX_new ();
|
||||||
|
// T = 80 random bytes
|
||||||
|
uint8_t T[80];
|
||||||
|
RAND_bytes (T, 80);
|
||||||
|
// calculate r = H*(T || publickey || data)
|
||||||
|
SHA512_CTX ctx;
|
||||||
|
SHA512_Init (&ctx);
|
||||||
|
SHA512_Update (&ctx, T, 80);
|
||||||
|
SHA512_Update (&ctx, publicKeyEncoded, 32);
|
||||||
|
SHA512_Update (&ctx, buf, len); // data
|
||||||
|
uint8_t digest[64];
|
||||||
|
SHA512_Final (digest, &ctx);
|
||||||
|
BIGNUM * r = DecodeBN<64> (digest);
|
||||||
|
BN_mod (r, r, l, bnCtx); // % l
|
||||||
|
EncodeBN (r, digest, 32);
|
||||||
|
// calculate R
|
||||||
|
uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf
|
||||||
|
EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R);
|
||||||
|
// calculate S
|
||||||
|
SHA512_Init (&ctx);
|
||||||
|
SHA512_Update (&ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R
|
||||||
|
SHA512_Update (&ctx, publicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key
|
||||||
|
SHA512_Update (&ctx, buf, len); // data
|
||||||
|
SHA512_Final (digest, &ctx);
|
||||||
|
BIGNUM * h = DecodeBN<64> (digest);
|
||||||
|
// S = (r + h*a) % l
|
||||||
|
BIGNUM * a = DecodeBN<EDDSA25519_PRIVATE_KEY_LENGTH> (privateKey);
|
||||||
|
BN_mod_mul (h, h, a, l, bnCtx); // %l
|
||||||
|
BN_mod_add (h, h, r, l, bnCtx); // %l
|
||||||
|
memcpy (signature, R, EDDSA25519_SIGNATURE_LENGTH/2);
|
||||||
|
EncodeBN (h, signature + EDDSA25519_SIGNATURE_LENGTH/2, EDDSA25519_SIGNATURE_LENGTH/2); // S
|
||||||
|
BN_free (r); BN_free (h); BN_free (a);
|
||||||
|
BN_CTX_free (bnCtx);
|
||||||
|
}
|
||||||
|
|
||||||
EDDSAPoint Ed25519::Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const
|
EDDSAPoint Ed25519::Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const
|
||||||
{
|
{
|
||||||
// x3 = (x1*y2+y1*x2)*(z1*z2-d*t1*t2)
|
// x3 = (x1*y2+y1*x2)*(z1*z2-d*t1*t2)
|
||||||
|
@ -514,6 +552,18 @@ namespace crypto
|
||||||
expandedKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] |= 0x40; // set second bit
|
expandedKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] |= 0x40; // set second bit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ed25519::CreateRedDSAPrivateKey (uint8_t * priv)
|
||||||
|
{
|
||||||
|
uint8_t seed[32];
|
||||||
|
RAND_bytes (seed, 32);
|
||||||
|
BIGNUM * p = DecodeBN<32> (seed);
|
||||||
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
|
BN_mod (p, p, l, ctx); // % l
|
||||||
|
EncodeBN (p, priv, 32);
|
||||||
|
BN_CTX_free (ctx);
|
||||||
|
BN_free (p);
|
||||||
|
}
|
||||||
|
|
||||||
static std::unique_ptr<Ed25519> g_Ed25519;
|
static std::unique_ptr<Ed25519> g_Ed25519;
|
||||||
std::unique_ptr<Ed25519>& GetEd25519 ()
|
std::unique_ptr<Ed25519>& GetEd25519 ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,9 +84,11 @@ namespace crypto
|
||||||
|
|
||||||
bool Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const;
|
bool Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const;
|
||||||
void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const;
|
void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const;
|
||||||
|
void SignRedDSA (const uint8_t * privateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const;
|
||||||
|
|
||||||
static void ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey); // key - 32 bytes, expandedKey - 64 bytes
|
static void ExpandPrivateKey (const uint8_t * key, uint8_t * expandedKey); // key - 32 bytes, expandedKey - 64 bytes
|
||||||
|
void CreateRedDSAPrivateKey (uint8_t * priv); // priv is 32 bytes
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
EDDSAPoint Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const;
|
EDDSAPoint Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const;
|
||||||
|
|
|
@ -338,12 +338,13 @@ namespace data
|
||||||
case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
|
case SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
|
||||||
return new i2p::crypto::ECDSAP521Verifier ();
|
return new i2p::crypto::ECDSAP521Verifier ();
|
||||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
|
||||||
return new i2p::crypto::EDDSA25519Verifier ();
|
return new i2p::crypto::EDDSA25519Verifier ();
|
||||||
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
|
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
|
||||||
return new i2p::crypto::GOSTR3410_256_Verifier (i2p::crypto::eGOSTR3410CryptoProA);
|
return new i2p::crypto::GOSTR3410_256_Verifier (i2p::crypto::eGOSTR3410CryptoProA);
|
||||||
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
|
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
|
||||||
return new i2p::crypto::GOSTR3410_512_Verifier (i2p::crypto::eGOSTR3410TC26A512);
|
return new i2p::crypto::GOSTR3410_512_Verifier (i2p::crypto::eGOSTR3410TC26A512);
|
||||||
|
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
||||||
|
return new i2p::crypto::RedDSA25519Verifier ();
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
case SIGNING_KEY_TYPE_RSA_SHA256_2048:
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
case SIGNING_KEY_TYPE_RSA_SHA384_3072:
|
||||||
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
case SIGNING_KEY_TYPE_RSA_SHA512_4096:
|
||||||
|
@ -611,7 +612,6 @@ namespace data
|
||||||
LogPrint (eLogError, "Identity: RSA signing key type ", (int)m_Public->GetSigningKeyType (), " is not supported");
|
LogPrint (eLogError, "Identity: RSA signing key type ", (int)m_Public->GetSigningKeyType (), " is not supported");
|
||||||
break;
|
break;
|
||||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
|
||||||
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, IsOfflineSignature () ? nullptr: m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH)); // TODO: remove public key check
|
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, IsOfflineSignature () ? nullptr: m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH)); // TODO: remove public key check
|
||||||
break;
|
break;
|
||||||
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
|
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
|
||||||
|
@ -620,6 +620,9 @@ namespace data
|
||||||
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
|
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
|
||||||
m_Signer.reset (new i2p::crypto::GOSTR3410_512_Signer (i2p::crypto::eGOSTR3410TC26A512, m_SigningPrivateKey));
|
m_Signer.reset (new i2p::crypto::GOSTR3410_512_Signer (i2p::crypto::eGOSTR3410TC26A512, m_SigningPrivateKey));
|
||||||
break;
|
break;
|
||||||
|
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
||||||
|
m_Signer.reset (new i2p::crypto::RedDSA25519Signer (m_SigningPrivateKey));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogError, "Identity: Signing key type ", (int)m_Public->GetSigningKeyType (), " is not supported");
|
LogPrint (eLogError, "Identity: Signing key type ", (int)m_Public->GetSigningKeyType (), " is not supported");
|
||||||
}
|
}
|
||||||
|
@ -704,7 +707,6 @@ namespace data
|
||||||
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
|
LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Creating EdDSA");
|
||||||
// no break here
|
// no break here
|
||||||
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
|
||||||
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
|
||||||
i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub);
|
i2p::crypto::CreateEDDSA25519RandomKeys (priv, pub);
|
||||||
break;
|
break;
|
||||||
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
|
case SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
|
||||||
|
@ -713,6 +715,9 @@ namespace data
|
||||||
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
|
case SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
|
||||||
i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A512, priv, pub);
|
i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A512, priv, pub);
|
||||||
break;
|
break;
|
||||||
|
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
|
||||||
|
i2p::crypto::CreateRedDSA25519RandomKeys (priv, pub);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogWarning, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1");
|
LogPrint (eLogWarning, "Identity: Signing key type ", (int)type, " is not supported. Create DSA-SHA1");
|
||||||
i2p::crypto::CreateDSARandomKeys (priv, pub); // DSA-SHA1
|
i2p::crypto::CreateDSARandomKeys (priv, pub); // DSA-SHA1
|
||||||
|
|
|
@ -487,6 +487,42 @@ namespace crypto
|
||||||
typedef GOSTR3410Signer<GOSTR3411_256_Hash> GOSTR3410_256_Signer;
|
typedef GOSTR3410Signer<GOSTR3411_256_Hash> GOSTR3410_256_Signer;
|
||||||
typedef GOSTR3410Verifier<GOSTR3411_512_Hash> GOSTR3410_512_Verifier;
|
typedef GOSTR3410Verifier<GOSTR3411_512_Hash> GOSTR3410_512_Verifier;
|
||||||
typedef GOSTR3410Signer<GOSTR3411_512_Hash> GOSTR3410_512_Signer;
|
typedef GOSTR3410Signer<GOSTR3411_512_Hash> GOSTR3410_512_Signer;
|
||||||
|
|
||||||
|
// RedDSA
|
||||||
|
typedef EDDSA25519Verifier RedDSA25519Verifier;
|
||||||
|
class RedDSA25519Signer: public Signer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
RedDSA25519Signer (const uint8_t * signingPrivateKey)
|
||||||
|
{
|
||||||
|
memcpy (m_PrivateKey, signingPrivateKey, EDDSA25519_PRIVATE_KEY_LENGTH);
|
||||||
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
|
auto publicKey = GetEd25519 ()->GeneratePublicKey (m_PrivateKey, ctx);
|
||||||
|
GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx);
|
||||||
|
BN_CTX_free (ctx);
|
||||||
|
}
|
||||||
|
~RedDSA25519Signer () {};
|
||||||
|
|
||||||
|
void Sign (const uint8_t * buf, int len, uint8_t * signature) const
|
||||||
|
{
|
||||||
|
GetEd25519 ()->SignRedDSA (m_PrivateKey, m_PublicKeyEncoded, buf, len, signature);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; // for keys creation
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint8_t m_PrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH];
|
||||||
|
uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH];
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void CreateRedDSA25519RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey)
|
||||||
|
{
|
||||||
|
GetEd25519 ()->CreateRedDSAPrivateKey (signingPrivateKey);
|
||||||
|
RedDSA25519Signer signer (signingPrivateKey);
|
||||||
|
memcpy (signingPublicKey, signer.GetPublicKey (), EDDSA25519_PUBLIC_KEY_LENGTH);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue