|
|
@ -432,6 +432,9 @@ namespace data |
|
|
|
m_Public = std::make_shared<IdentityEx>(Identity (keys)); |
|
|
|
m_Public = std::make_shared<IdentityEx>(Identity (keys)); |
|
|
|
memcpy (m_PrivateKey, keys.privateKey, 256); // 256
|
|
|
|
memcpy (m_PrivateKey, keys.privateKey, 256); // 256
|
|
|
|
memcpy (m_SigningPrivateKey, keys.signingPrivateKey, m_Public->GetSigningPrivateKeyLen ()); |
|
|
|
memcpy (m_SigningPrivateKey, keys.signingPrivateKey, m_Public->GetSigningPrivateKeyLen ()); |
|
|
|
|
|
|
|
m_OfflineSignature.resize (0); |
|
|
|
|
|
|
|
m_TransientSignatureLen = 0; |
|
|
|
|
|
|
|
m_TransientSigningPrivateKeyLen = 0; |
|
|
|
m_Signer = nullptr; |
|
|
|
m_Signer = nullptr; |
|
|
|
CreateSigner (); |
|
|
|
CreateSigner (); |
|
|
|
return *this; |
|
|
|
return *this; |
|
|
@ -441,12 +444,23 @@ namespace data |
|
|
|
{ |
|
|
|
{ |
|
|
|
m_Public = std::make_shared<IdentityEx>(*other.m_Public); |
|
|
|
m_Public = std::make_shared<IdentityEx>(*other.m_Public); |
|
|
|
memcpy (m_PrivateKey, other.m_PrivateKey, 256); // 256
|
|
|
|
memcpy (m_PrivateKey, other.m_PrivateKey, 256); // 256
|
|
|
|
memcpy (m_SigningPrivateKey, other.m_SigningPrivateKey, m_Public->GetSigningPrivateKeyLen ()); |
|
|
|
m_OfflineSignature = other.m_OfflineSignature; |
|
|
|
|
|
|
|
m_TransientSignatureLen = other.m_TransientSignatureLen; |
|
|
|
|
|
|
|
m_TransientSigningPrivateKeyLen = other.m_TransientSigningPrivateKeyLen; |
|
|
|
|
|
|
|
memcpy (m_SigningPrivateKey, other.m_SigningPrivateKey, m_TransientSigningPrivateKeyLen > 0 ? m_TransientSigningPrivateKeyLen : m_Public->GetSigningPrivateKeyLen ()); |
|
|
|
m_Signer = nullptr; |
|
|
|
m_Signer = nullptr; |
|
|
|
CreateSigner (); |
|
|
|
CreateSigner (); |
|
|
|
return *this; |
|
|
|
return *this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t PrivateKeys::GetFullLen () const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
size_t ret = m_Public->GetFullLen () + 256 + m_Public->GetSigningPrivateKeyLen (); |
|
|
|
|
|
|
|
if (IsOfflineSignature ()) |
|
|
|
|
|
|
|
ret += m_OfflineSignature.size () + m_TransientSigningPrivateKeyLen; |
|
|
|
|
|
|
|
return ret; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
size_t PrivateKeys::FromBuffer (const uint8_t * buf, size_t len) |
|
|
|
size_t PrivateKeys::FromBuffer (const uint8_t * buf, size_t len) |
|
|
|
{ |
|
|
|
{ |
|
|
|
m_Public = std::make_shared<IdentityEx>(); |
|
|
|
m_Public = std::make_shared<IdentityEx>(); |
|
|
@ -455,11 +469,50 @@ namespace data |
|
|
|
memcpy (m_PrivateKey, buf + ret, 256); // private key always 256
|
|
|
|
memcpy (m_PrivateKey, buf + ret, 256); // private key always 256
|
|
|
|
ret += 256; |
|
|
|
ret += 256; |
|
|
|
size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); |
|
|
|
size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); |
|
|
|
if(signingPrivateKeySize + ret > len) return 0; // overflow
|
|
|
|
if(signingPrivateKeySize + ret > len || signingPrivateKeySize > 128) return 0; // overflow
|
|
|
|
memcpy (m_SigningPrivateKey, buf + ret, signingPrivateKeySize); |
|
|
|
memcpy (m_SigningPrivateKey, buf + ret, signingPrivateKeySize); |
|
|
|
ret += signingPrivateKeySize; |
|
|
|
ret += signingPrivateKeySize; |
|
|
|
m_Signer = nullptr; |
|
|
|
m_Signer = nullptr; |
|
|
|
CreateSigner (); |
|
|
|
// check if signing private key is all zeros
|
|
|
|
|
|
|
|
bool allzeros = true; |
|
|
|
|
|
|
|
for (size_t i = 0; i < signingPrivateKeySize; i++) |
|
|
|
|
|
|
|
if (m_SigningPrivateKey[i]) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
allzeros = false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (allzeros) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// offline information
|
|
|
|
|
|
|
|
const uint8_t * offlineInfo = buf + ret; |
|
|
|
|
|
|
|
ret += 4; // expires timestamp
|
|
|
|
|
|
|
|
SigningKeyType keyType = bufbe16toh (buf + ret); ret += 2; // key type
|
|
|
|
|
|
|
|
std::unique_ptr<i2p::crypto::Verifier> transientVerifier (IdentityEx::CreateVerifier (keyType)); |
|
|
|
|
|
|
|
if (!transientVerifier) return 0; |
|
|
|
|
|
|
|
auto keyLen = transientVerifier->GetPublicKeyLen (); |
|
|
|
|
|
|
|
if (keyLen + ret > len) return 0; |
|
|
|
|
|
|
|
transientVerifier->SetPublicKey (buf + ret); ret += keyLen; |
|
|
|
|
|
|
|
if (m_Public->GetSignatureLen () + ret > len) return 0; |
|
|
|
|
|
|
|
if (!m_Public->Verify (offlineInfo, keyLen + 6, buf + ret)) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LogPrint (eLogError, "Identity: offline signature verification failed"); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ret += m_Public->GetSignatureLen (); |
|
|
|
|
|
|
|
m_TransientSignatureLen = transientVerifier->GetSignatureLen (); |
|
|
|
|
|
|
|
// copy offline signature
|
|
|
|
|
|
|
|
size_t offlineInfoLen = buf + ret - offlineInfo; |
|
|
|
|
|
|
|
m_OfflineSignature.resize (offlineInfoLen); |
|
|
|
|
|
|
|
memcpy (m_OfflineSignature.data (), offlineInfo, offlineInfoLen); |
|
|
|
|
|
|
|
// override signing private key
|
|
|
|
|
|
|
|
m_TransientSigningPrivateKeyLen = transientVerifier->GetPrivateKeyLen (); |
|
|
|
|
|
|
|
if (m_TransientSigningPrivateKeyLen + ret > len || m_TransientSigningPrivateKeyLen > 128) return 0; |
|
|
|
|
|
|
|
memcpy (m_SigningPrivateKey, buf + ret, m_TransientSigningPrivateKeyLen); |
|
|
|
|
|
|
|
ret += m_TransientSigningPrivateKeyLen; |
|
|
|
|
|
|
|
CreateSigner (keyType); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
CreateSigner (m_Public->GetSigningKeyType ()); |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -470,8 +523,23 @@ namespace data |
|
|
|
ret += 256; |
|
|
|
ret += 256; |
|
|
|
size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); |
|
|
|
size_t signingPrivateKeySize = m_Public->GetSigningPrivateKeyLen (); |
|
|
|
if(ret + signingPrivateKeySize > len) return 0; // overflow
|
|
|
|
if(ret + signingPrivateKeySize > len) return 0; // overflow
|
|
|
|
|
|
|
|
if (IsOfflineSignature ()) |
|
|
|
|
|
|
|
memset (buf + ret, 0, signingPrivateKeySize); |
|
|
|
|
|
|
|
else |
|
|
|
memcpy (buf + ret, m_SigningPrivateKey, signingPrivateKeySize); |
|
|
|
memcpy (buf + ret, m_SigningPrivateKey, signingPrivateKeySize); |
|
|
|
ret += signingPrivateKeySize; |
|
|
|
ret += signingPrivateKeySize; |
|
|
|
|
|
|
|
if (IsOfflineSignature ()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// offline signature
|
|
|
|
|
|
|
|
auto offlineSignatureLen = m_OfflineSignature.size (); |
|
|
|
|
|
|
|
if (ret + offlineSignatureLen > len) return 0; |
|
|
|
|
|
|
|
memcpy (buf + ret, m_OfflineSignature.data (), offlineSignatureLen); |
|
|
|
|
|
|
|
ret += offlineSignatureLen; |
|
|
|
|
|
|
|
// transient private key
|
|
|
|
|
|
|
|
if (ret + m_TransientSigningPrivateKeyLen > len) return 0; |
|
|
|
|
|
|
|
memcpy (buf + ret, m_SigningPrivateKey, m_TransientSigningPrivateKeyLen); |
|
|
|
|
|
|
|
ret += m_TransientSigningPrivateKeyLen; |
|
|
|
|
|
|
|
} |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -505,9 +573,17 @@ namespace data |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void PrivateKeys::CreateSigner () const |
|
|
|
void PrivateKeys::CreateSigner () const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (IsOfflineSignature ()) |
|
|
|
|
|
|
|
CreateSigner (bufbe16toh (m_OfflineSignature.data () + 4)); // key type
|
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
CreateSigner (m_Public->GetSigningKeyType ()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrivateKeys::CreateSigner (SigningKeyType keyType) const |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (m_Signer) return; |
|
|
|
if (m_Signer) return; |
|
|
|
switch (m_Public->GetSigningKeyType ()) |
|
|
|
switch (keyType) |
|
|
|
{ |
|
|
|
{ |
|
|
|
case SIGNING_KEY_TYPE_DSA_SHA1: |
|
|
|
case SIGNING_KEY_TYPE_DSA_SHA1: |
|
|
|
m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey)); |
|
|
|
m_Signer.reset (new i2p::crypto::DSASigner (m_SigningPrivateKey, m_Public->GetStandardIdentity ().signingKey)); |
|
|
@ -527,7 +603,7 @@ 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: |
|
|
|
m_Signer.reset (new i2p::crypto::EDDSA25519Signer (m_SigningPrivateKey, m_Public->GetStandardIdentity ().certificate - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH)); |
|
|
|
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: |
|
|
|
m_Signer.reset (new i2p::crypto::GOSTR3410_256_Signer (i2p::crypto::eGOSTR3410CryptoProA, m_SigningPrivateKey)); |
|
|
|
m_Signer.reset (new i2p::crypto::GOSTR3410_256_Signer (i2p::crypto::eGOSTR3410CryptoProA, m_SigningPrivateKey)); |
|
|
@ -540,6 +616,11 @@ namespace data |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size_t PrivateKeys::GetSignatureLen () const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return IsOfflineSignature () ? m_TransientSignatureLen : m_Public->GetSignatureLen (); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
uint8_t * PrivateKeys::GetPadding() |
|
|
|
uint8_t * PrivateKeys::GetPadding() |
|
|
|
{ |
|
|
|
{ |
|
|
|
if(m_Public->GetSigningKeyType () == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519) |
|
|
|
if(m_Public->GetSigningKeyType () == SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519) |
|
|
@ -582,16 +663,31 @@ namespace data |
|
|
|
PrivateKeys keys; |
|
|
|
PrivateKeys keys; |
|
|
|
// signature
|
|
|
|
// signature
|
|
|
|
uint8_t signingPublicKey[512]; // signing public key is 512 bytes max
|
|
|
|
uint8_t signingPublicKey[512]; // signing public key is 512 bytes max
|
|
|
|
|
|
|
|
GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, signingPublicKey); |
|
|
|
|
|
|
|
// encryption
|
|
|
|
|
|
|
|
uint8_t publicKey[256]; |
|
|
|
|
|
|
|
GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey); |
|
|
|
|
|
|
|
// identity
|
|
|
|
|
|
|
|
keys.m_Public = std::make_shared<IdentityEx> (publicKey, signingPublicKey, type, cryptoType); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
keys.CreateSigner (); |
|
|
|
|
|
|
|
return keys; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrivateKeys::GenerateSigningKeyPair (SigningKeyType type, uint8_t * priv, uint8_t * pub) |
|
|
|
|
|
|
|
{ |
|
|
|
switch (type) |
|
|
|
switch (type) |
|
|
|
{ |
|
|
|
{ |
|
|
|
case SIGNING_KEY_TYPE_ECDSA_SHA256_P256: |
|
|
|
case SIGNING_KEY_TYPE_ECDSA_SHA256_P256: |
|
|
|
i2p::crypto::CreateECDSAP256RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); |
|
|
|
i2p::crypto::CreateECDSAP256RandomKeys (priv, pub); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case SIGNING_KEY_TYPE_ECDSA_SHA384_P384: |
|
|
|
case SIGNING_KEY_TYPE_ECDSA_SHA384_P384: |
|
|
|
i2p::crypto::CreateECDSAP384RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); |
|
|
|
i2p::crypto::CreateECDSAP384RandomKeys (priv, pub); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case SIGNING_KEY_TYPE_ECDSA_SHA512_P521: |
|
|
|
case SIGNING_KEY_TYPE_ECDSA_SHA512_P521: |
|
|
|
i2p::crypto::CreateECDSAP521RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); |
|
|
|
i2p::crypto::CreateECDSAP521RandomKeys (priv, pub); |
|
|
|
break; |
|
|
|
break; |
|
|
|
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: |
|
|
@ -599,28 +695,18 @@ 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: |
|
|
|
i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); |
|
|
|
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: |
|
|
|
i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410CryptoProA, keys.m_SigningPrivateKey, signingPublicKey); |
|
|
|
i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410CryptoProA, priv, pub); |
|
|
|
break; |
|
|
|
break; |
|
|
|
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, keys.m_SigningPrivateKey, signingPublicKey); |
|
|
|
i2p::crypto::CreateGOSTR3410RandomKeys (i2p::crypto::eGOSTR3410TC26A512, priv, pub); |
|
|
|
break; |
|
|
|
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"); |
|
|
|
return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1
|
|
|
|
i2p::crypto::CreateDSARandomKeys (priv, pub); // DSA-SHA1
|
|
|
|
} |
|
|
|
|
|
|
|
// encryption
|
|
|
|
|
|
|
|
uint8_t publicKey[256]; |
|
|
|
|
|
|
|
GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey); |
|
|
|
|
|
|
|
// identity
|
|
|
|
|
|
|
|
keys.m_Public = std::make_shared<IdentityEx> (publicKey, signingPublicKey, type, cryptoType); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
keys.CreateSigner (); |
|
|
|
|
|
|
|
return keys; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return PrivateKeys (i2p::data::CreateRandomKeys ()); // DSA-SHA1
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void PrivateKeys::GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub) |
|
|
|
void PrivateKeys::GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub) |
|
|
@ -642,6 +728,27 @@ namespace data |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PrivateKeys PrivateKeys::CreateOfflineKeys (SigningKeyType type, uint32_t expires) const |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
PrivateKeys keys (*this); |
|
|
|
|
|
|
|
std::unique_ptr<i2p::crypto::Verifier> verifier (IdentityEx::CreateVerifier (type)); |
|
|
|
|
|
|
|
if (verifier) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
size_t pubKeyLen = verifier->GetPublicKeyLen (); |
|
|
|
|
|
|
|
keys.m_TransientSigningPrivateKeyLen = verifier->GetPrivateKeyLen (); |
|
|
|
|
|
|
|
keys.m_TransientSignatureLen = verifier->GetSignatureLen (); |
|
|
|
|
|
|
|
keys.m_OfflineSignature.resize (pubKeyLen + m_Public->GetSignatureLen () + 6); |
|
|
|
|
|
|
|
htobe32buf (keys.m_OfflineSignature.data (), expires); // expires
|
|
|
|
|
|
|
|
htobe16buf (keys.m_OfflineSignature.data () + 4, type); // type
|
|
|
|
|
|
|
|
GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, keys.m_OfflineSignature.data () + 6); // public key
|
|
|
|
|
|
|
|
Sign (keys.m_OfflineSignature.data (), pubKeyLen + 6, keys.m_OfflineSignature.data () + 6 + pubKeyLen); // signature
|
|
|
|
|
|
|
|
// recreate signer
|
|
|
|
|
|
|
|
keys.m_Signer = nullptr; |
|
|
|
|
|
|
|
keys.CreateSigner (type); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return keys; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Keys CreateRandomKeys () |
|
|
|
Keys CreateRandomKeys () |
|
|
|
{ |
|
|
|
{ |
|
|
|
Keys keys; |
|
|
|
Keys keys; |
|
|
|