mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
initial commit
This commit is contained in:
commit
c2da007f40
1610 changed files with 398047 additions and 0 deletions
280
crypto/ellcurve/Ed25519.cpp
Normal file
280
crypto/ellcurve/Ed25519.cpp
Normal file
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
#include "Ed25519.h"
|
||||
|
||||
#include "td/utils/Random.h"
|
||||
|
||||
namespace crypto {
|
||||
namespace Ed25519 {
|
||||
|
||||
bool all_bytes_same(const unsigned char *str, std::size_t size) {
|
||||
unsigned char c = str[0];
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
if (str[i] != c) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PublicKey::clear(void) {
|
||||
if (inited != pk_empty) {
|
||||
std::memset(pubkey, 0, pubkey_bytes);
|
||||
PubKey.zeroize();
|
||||
PubKey_xz.zeroize();
|
||||
}
|
||||
inited = pk_empty;
|
||||
}
|
||||
|
||||
PublicKey::PublicKey(const unsigned char pub_key[pubkey_bytes])
|
||||
: inited(pk_empty), PubKey(ellcurve::Fp25519()), PubKey_xz(ellcurve::Fp25519()) {
|
||||
import_public_key(pub_key);
|
||||
}
|
||||
|
||||
PublicKey::PublicKey(const ellcurve::TwEdwardsCurve::SegrePoint &Pub_Key)
|
||||
: inited(pk_empty), PubKey(ellcurve::Fp25519()), PubKey_xz(ellcurve::Fp25519()) {
|
||||
import_public_key(Pub_Key);
|
||||
}
|
||||
|
||||
bool PublicKey::import_public_key(const unsigned char pub_key[pubkey_bytes]) {
|
||||
clear();
|
||||
if (all_bytes_same(pub_key, pubkey_bytes)) {
|
||||
return false;
|
||||
}
|
||||
bool ok = false;
|
||||
PubKey = ellcurve::Ed25519().import_point(pub_key, ok);
|
||||
if (!ok) {
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
std::memcpy(pubkey, pub_key, pubkey_bytes);
|
||||
PubKey_xz.X = PubKey.Z + PubKey.Y;
|
||||
PubKey_xz.Z = PubKey.Z - PubKey.Y;
|
||||
inited = pk_init;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PublicKey::import_public_key(const ellcurve::TwEdwardsCurve::SegrePoint &Pub_Key) {
|
||||
clear();
|
||||
if (!Pub_Key.is_valid()) {
|
||||
return false;
|
||||
}
|
||||
PubKey = Pub_Key;
|
||||
PubKey_xz.X = PubKey.Z + PubKey.Y;
|
||||
PubKey_xz.Z = PubKey.Z - PubKey.Y;
|
||||
inited = pk_init;
|
||||
|
||||
if (!PubKey.export_point(pubkey)) {
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PublicKey::export_public_key(unsigned char pubkey_buffer[pubkey_bytes]) const {
|
||||
if (inited != pk_init) {
|
||||
std::memset(pubkey_buffer, 0, pubkey_bytes);
|
||||
return false;
|
||||
} else {
|
||||
std::memcpy(pubkey_buffer, pubkey, pubkey_bytes);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool PublicKey::check_message_signature(const unsigned char signature[sign_bytes], const unsigned char *message,
|
||||
std::size_t msg_size) {
|
||||
if (inited != pk_init) {
|
||||
return false;
|
||||
}
|
||||
unsigned char hash[64];
|
||||
{
|
||||
digest::SHA512 hasher(signature, 32);
|
||||
hasher.feed(pubkey, 32);
|
||||
hasher.feed(message, msg_size);
|
||||
hasher.extract(hash);
|
||||
}
|
||||
auto &E = ellcurve::Ed25519();
|
||||
const arith::Bignum &L = E.get_ell();
|
||||
arith::Bignum H, S;
|
||||
S.import_lsb(signature + 32, 32);
|
||||
H.import_lsb(hash, 64);
|
||||
H %= L;
|
||||
H = L - H;
|
||||
auto sG = E.power_gen(S);
|
||||
auto hA = E.power_point(PubKey, H);
|
||||
auto pR1 = E.add_points(sG, hA);
|
||||
unsigned char pR1_bytes[32];
|
||||
if (!pR1.export_point(pR1_bytes)) {
|
||||
return false;
|
||||
}
|
||||
return !std::memcmp(pR1_bytes, signature, 32);
|
||||
}
|
||||
|
||||
// ---------------------
|
||||
class PrivateKey;
|
||||
|
||||
bool PrivateKey::random_private_key(bool strong) {
|
||||
inited = false;
|
||||
if (!prng::rand_gen().rand_bytes(privkey, privkey_bytes, strong)) {
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
return process_private_key();
|
||||
}
|
||||
|
||||
void PrivateKey::clear(void) {
|
||||
std::memset(privkey, 0, privkey_bytes);
|
||||
std::memset(priv_salt, 0, sizeof(priv_salt));
|
||||
priv_exp.clear();
|
||||
PubKey.clear();
|
||||
inited = false;
|
||||
}
|
||||
|
||||
bool PrivateKey::import_private_key(const unsigned char pk[privkey_bytes]) {
|
||||
clear();
|
||||
if (all_bytes_same(pk, privkey_bytes)) {
|
||||
return false;
|
||||
}
|
||||
std::memcpy(privkey, pk, privkey_bytes);
|
||||
return process_private_key();
|
||||
}
|
||||
|
||||
bool PrivateKey::export_private_key(unsigned char pk[privkey_bytes]) const { // careful!
|
||||
if (!inited) {
|
||||
std::memset(pk, 0, privkey_bytes);
|
||||
return false;
|
||||
} else {
|
||||
std::memcpy(pk, privkey, privkey_bytes);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool PrivateKey::process_private_key() {
|
||||
unsigned char buff[64];
|
||||
digest::hash_str<digest::SHA512>(buff, privkey, privkey_bytes);
|
||||
std::memcpy(priv_salt, buff + 32, 32);
|
||||
buff[0] = (unsigned char)(buff[0] & -8);
|
||||
buff[31] = (unsigned char)((buff[31] | 0x40) & ~0x80);
|
||||
priv_exp.import_lsb(buff, 32);
|
||||
PubKey = ellcurve::Ed25519().power_gen(priv_exp, true); // uniform
|
||||
inited = PubKey.ok();
|
||||
if (!inited) {
|
||||
clear();
|
||||
}
|
||||
return inited;
|
||||
}
|
||||
|
||||
bool PrivateKey::compute_shared_secret(unsigned char secret[shared_secret_bytes], const PublicKey &Pub) {
|
||||
if (!inited || !Pub.ok()) {
|
||||
std::memset(secret, 0, shared_secret_bytes);
|
||||
*(long *)secret = static_cast<long>(td::Random::fast_uint64());
|
||||
return false;
|
||||
}
|
||||
// uniform power!
|
||||
auto P = ellcurve::Curve25519().power_xz(Pub.get_point_xz(), priv_exp);
|
||||
if (P.is_infty()) {
|
||||
std::memset(secret, 0, shared_secret_bytes);
|
||||
*(long *)secret = static_cast<long>(td::Random::fast_uint64());
|
||||
return false;
|
||||
}
|
||||
P.export_point_u(secret);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrivateKey::compute_temp_shared_secret(unsigned char secret[shared_secret_bytes],
|
||||
const unsigned char temp_pub_key[pubkey_bytes]) {
|
||||
PublicKey tempPubkey(temp_pub_key);
|
||||
if (!tempPubkey.ok()) {
|
||||
return false;
|
||||
}
|
||||
return compute_shared_secret(secret, tempPubkey);
|
||||
}
|
||||
|
||||
bool PrivateKey::sign_message(unsigned char signature[sign_bytes], const unsigned char *message, std::size_t msg_size) {
|
||||
if (!inited) {
|
||||
std::memset(signature, 0, sign_bytes);
|
||||
return false;
|
||||
}
|
||||
unsigned char r_bytes[64];
|
||||
digest::hash_two_str<digest::SHA512>(r_bytes, priv_salt, 32, message, msg_size);
|
||||
const arith::Bignum &L = ellcurve::Ed25519().get_ell();
|
||||
arith::Bignum eR;
|
||||
eR.import_lsb(r_bytes, 64);
|
||||
eR %= L;
|
||||
std::memset(r_bytes, 0, sizeof(r_bytes));
|
||||
|
||||
// uniform power
|
||||
auto pR = ellcurve::Ed25519().power_gen(eR, true);
|
||||
|
||||
auto ok = pR.export_point(signature, true);
|
||||
(void)ok;
|
||||
assert(ok);
|
||||
{
|
||||
digest::SHA512 hasher(signature, 32);
|
||||
hasher.feed(PubKey.get_pubkey_ptr(), 32);
|
||||
hasher.feed(message, msg_size);
|
||||
hasher.extract(r_bytes);
|
||||
}
|
||||
arith::Bignum S;
|
||||
S.import_lsb(r_bytes, 64);
|
||||
S %= L;
|
||||
S *= priv_exp;
|
||||
S += eR;
|
||||
S %= L;
|
||||
eR.clear();
|
||||
S.export_lsb(signature + 32, 32);
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------
|
||||
class TempKeyGenerator;
|
||||
|
||||
unsigned char *TempKeyGenerator::get_temp_private_key(unsigned char *to, const unsigned char *message, std::size_t size,
|
||||
const unsigned char *rand,
|
||||
std::size_t rand_size) { // rand may be 0
|
||||
digest::SHA256 hasher(message, size);
|
||||
hasher.feed(random_salt, salt_size);
|
||||
if (rand && rand_size) {
|
||||
hasher.feed(rand, rand_size);
|
||||
}
|
||||
if (!to) {
|
||||
to = buffer;
|
||||
}
|
||||
hasher.extract(to);
|
||||
//++ *((long *)random_salt);
|
||||
return to;
|
||||
}
|
||||
|
||||
void TempKeyGenerator::create_temp_private_key(PrivateKey &pk, const unsigned char *message, std::size_t size,
|
||||
const unsigned char *rand, std::size_t rand_size) {
|
||||
pk.import_private_key(get_temp_private_key(buffer, message, size, rand, rand_size));
|
||||
std::memset(buffer, 0, privkey_bytes);
|
||||
}
|
||||
|
||||
bool TempKeyGenerator::create_temp_shared_secret(unsigned char temp_pub_key[pubkey_bytes],
|
||||
unsigned char shared_secret[shared_secret_bytes],
|
||||
const PublicKey &recipientPubKey, const unsigned char *message,
|
||||
std::size_t size, const unsigned char *rand, std::size_t rand_size) {
|
||||
PrivateKey tmpPk;
|
||||
create_temp_private_key(tmpPk, message, size, rand, rand_size);
|
||||
return tmpPk.export_public_key(temp_pub_key) && tmpPk.compute_shared_secret(shared_secret, recipientPubKey);
|
||||
}
|
||||
|
||||
} // namespace Ed25519
|
||||
} // namespace crypto
|
188
crypto/ellcurve/Ed25519.h
Normal file
188
crypto/ellcurve/Ed25519.h
Normal file
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include "ellcurve/Montgomery.h"
|
||||
#include "ellcurve/TwEdwards.h"
|
||||
#include "openssl/digest.h"
|
||||
#include "openssl/rand.hpp"
|
||||
#include <assert.h>
|
||||
#include <cstring>
|
||||
|
||||
#include "td/utils/buffer.h"
|
||||
|
||||
namespace crypto {
|
||||
namespace Ed25519 {
|
||||
|
||||
const int privkey_bytes = 32;
|
||||
const int pubkey_bytes = 32;
|
||||
const int sign_bytes = 64;
|
||||
const int shared_secret_bytes = 32;
|
||||
|
||||
class PublicKey {
|
||||
enum { pk_empty, pk_xz, pk_init } inited;
|
||||
unsigned char pubkey[pubkey_bytes];
|
||||
ellcurve::TwEdwardsCurve::SegrePoint PubKey;
|
||||
ellcurve::MontgomeryCurve::PointXZ PubKey_xz;
|
||||
|
||||
public:
|
||||
PublicKey() : inited(pk_empty), PubKey(ellcurve::Fp25519()), PubKey_xz(ellcurve::Fp25519()) {
|
||||
}
|
||||
PublicKey(const unsigned char pub_key[pubkey_bytes]);
|
||||
PublicKey(td::Slice pub_key) : PublicKey(pub_key.ubegin()) {
|
||||
CHECK(pub_key.size() == pubkey_bytes);
|
||||
}
|
||||
PublicKey(const ellcurve::TwEdwardsCurve::SegrePoint &Pub_Key);
|
||||
|
||||
bool import_public_key(const unsigned char pub_key[pubkey_bytes]);
|
||||
bool import_public_key(td::Slice pub_key) {
|
||||
CHECK(pub_key.size() == pubkey_bytes);
|
||||
return import_public_key(pub_key.ubegin());
|
||||
}
|
||||
bool import_public_key(const ellcurve::TwEdwardsCurve::SegrePoint &Pub_Key);
|
||||
bool export_public_key(unsigned char pubkey_buffer[pubkey_bytes]) const;
|
||||
bool export_public_key(td::MutableSlice pubk) const {
|
||||
CHECK(pubk.size() == pubkey_bytes);
|
||||
return export_public_key(pubk.ubegin());
|
||||
}
|
||||
bool check_message_signature(const unsigned char signature[sign_bytes], const unsigned char *message,
|
||||
std::size_t msg_size);
|
||||
bool check_message_signature(td::Slice signature, td::Slice message) {
|
||||
CHECK(signature.size() == sign_bytes);
|
||||
return check_message_signature(signature.ubegin(), message.ubegin(), message.size());
|
||||
}
|
||||
|
||||
void clear();
|
||||
bool ok() const {
|
||||
return inited == pk_init;
|
||||
}
|
||||
|
||||
const unsigned char *get_pubkey_ptr() const {
|
||||
return inited == pk_init ? pubkey : 0;
|
||||
}
|
||||
const ellcurve::TwEdwardsCurve::SegrePoint &get_point() const {
|
||||
return PubKey;
|
||||
}
|
||||
const ellcurve::MontgomeryCurve::PointXZ &get_point_xz() const {
|
||||
return PubKey_xz;
|
||||
}
|
||||
};
|
||||
|
||||
class PrivateKey {
|
||||
public:
|
||||
struct priv_key_no_copy {};
|
||||
PrivateKey() : inited(false) {
|
||||
memset(privkey, 0, privkey_bytes);
|
||||
}
|
||||
PrivateKey(const unsigned char pk[privkey_bytes]) : inited(false) {
|
||||
memset(privkey, 0, privkey_bytes);
|
||||
import_private_key(pk);
|
||||
}
|
||||
PrivateKey(td::Slice pk) : inited(false) {
|
||||
CHECK(pk.size() == privkey_bytes);
|
||||
memset(privkey, 0, privkey_bytes);
|
||||
import_private_key(pk.ubegin());
|
||||
}
|
||||
~PrivateKey() {
|
||||
clear();
|
||||
}
|
||||
bool random_private_key(bool strong = false);
|
||||
bool import_private_key(const unsigned char pk[privkey_bytes]);
|
||||
bool import_private_key(td::Slice pk) {
|
||||
CHECK(pk.size() == privkey_bytes);
|
||||
return import_private_key(pk.ubegin());
|
||||
}
|
||||
bool export_private_key(unsigned char pk[privkey_bytes]) const; // careful!
|
||||
bool export_private_key(td::MutableSlice pk) const { // careful!
|
||||
return export_private_key(pk.ubegin());
|
||||
}
|
||||
bool export_public_key(unsigned char pubk[pubkey_bytes]) const {
|
||||
return PubKey.export_public_key(pubk);
|
||||
}
|
||||
bool export_public_key(td::MutableSlice pubk) const {
|
||||
return PubKey.export_public_key(pubk);
|
||||
}
|
||||
void clear();
|
||||
bool ok() const {
|
||||
return inited;
|
||||
}
|
||||
|
||||
// used for EdDSA (sign)
|
||||
bool sign_message(unsigned char signature[sign_bytes], const unsigned char *message, std::size_t msg_size);
|
||||
bool sign_message(td::MutableSlice signature, td::Slice message) {
|
||||
CHECK(signature.size() == sign_bytes);
|
||||
return sign_message(signature.ubegin(), message.ubegin(), message.size());
|
||||
}
|
||||
// used for ECDH (encrypt / decrypt)
|
||||
bool compute_shared_secret(unsigned char secret[shared_secret_bytes], const PublicKey &Pub);
|
||||
bool compute_shared_secret(td::MutableSlice secret, const PublicKey &Pub) {
|
||||
CHECK(secret.size() == shared_secret_bytes);
|
||||
return compute_shared_secret(secret.ubegin(), Pub);
|
||||
}
|
||||
// used for EC asymmetric decryption
|
||||
bool compute_temp_shared_secret(unsigned char secret[shared_secret_bytes],
|
||||
const unsigned char temp_pub_key[pubkey_bytes]);
|
||||
|
||||
const PublicKey &get_public_key() const {
|
||||
return PubKey;
|
||||
}
|
||||
|
||||
private:
|
||||
bool inited;
|
||||
unsigned char privkey[privkey_bytes];
|
||||
unsigned char priv_salt[32];
|
||||
arith::Bignum priv_exp;
|
||||
PublicKey PubKey;
|
||||
|
||||
bool process_private_key();
|
||||
PrivateKey(const PrivateKey &) {
|
||||
throw priv_key_no_copy();
|
||||
}
|
||||
PrivateKey &operator=(const PrivateKey &) {
|
||||
throw priv_key_no_copy();
|
||||
}
|
||||
};
|
||||
|
||||
// use one TempKeyGenerator object a lot of times
|
||||
class TempKeyGenerator {
|
||||
enum { salt_size = 64 };
|
||||
unsigned char random_salt[salt_size];
|
||||
unsigned char buffer[privkey_bytes];
|
||||
|
||||
public:
|
||||
TempKeyGenerator() {
|
||||
prng::rand_gen().strong_rand_bytes(random_salt, salt_size);
|
||||
}
|
||||
~TempKeyGenerator() {
|
||||
memset(random_salt, 0, salt_size);
|
||||
memset(buffer, 0, privkey_bytes);
|
||||
}
|
||||
|
||||
unsigned char *get_temp_private_key(unsigned char *to, const unsigned char *message, std::size_t size,
|
||||
const unsigned char *rand = 0, std::size_t rand_size = 0); // rand may be 0
|
||||
void create_temp_private_key(PrivateKey &pk, const unsigned char *message, std::size_t size,
|
||||
const unsigned char *rand = 0, std::size_t rand_size = 0);
|
||||
|
||||
// sets temp_pub_key and shared_secret for one-time asymmetric encryption of message
|
||||
bool create_temp_shared_secret(unsigned char temp_pub_key[pubkey_bytes], unsigned char secret[shared_secret_bytes],
|
||||
const PublicKey &recipientPubKey, const unsigned char *message, std::size_t size,
|
||||
const unsigned char *rand = 0, std::size_t rand_size = 0);
|
||||
};
|
||||
|
||||
} // namespace Ed25519
|
||||
} // namespace crypto
|
33
crypto/ellcurve/Fp25519.cpp
Normal file
33
crypto/ellcurve/Fp25519.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
#include "ellcurve/Fp25519.h"
|
||||
|
||||
namespace ellcurve {
|
||||
using namespace arith;
|
||||
|
||||
const Bignum& P25519() {
|
||||
static const Bignum P25519 = (Bignum(1) << 255) - 19;
|
||||
return P25519;
|
||||
}
|
||||
|
||||
td::Ref<ResidueRing> Fp25519() {
|
||||
static const td::Ref<ResidueRing> Fp25519(true, P25519());
|
||||
return Fp25519;
|
||||
}
|
||||
} // namespace ellcurve
|
32
crypto/ellcurve/Fp25519.h
Normal file
32
crypto/ellcurve/Fp25519.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include "common/refcnt.hpp"
|
||||
#include "openssl/residue.h"
|
||||
|
||||
namespace ellcurve {
|
||||
using namespace arith;
|
||||
|
||||
// returns 2^255-19
|
||||
const Bignum& P25519();
|
||||
|
||||
// residue ring modulo P25519
|
||||
td::Ref<ResidueRing> Fp25519();
|
||||
|
||||
} // namespace ellcurve
|
138
crypto/ellcurve/Montgomery.cpp
Normal file
138
crypto/ellcurve/Montgomery.cpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
#include "ellcurve/Montgomery.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace ellcurve {
|
||||
using namespace arith;
|
||||
|
||||
class MontgomeryCurve;
|
||||
|
||||
void MontgomeryCurve::init() {
|
||||
assert(!((a_short + 2) & 3) && a_short >= 0);
|
||||
}
|
||||
|
||||
void MontgomeryCurve::set_order_cofactor(const Bignum& order, int cof) {
|
||||
assert(order > 0);
|
||||
assert(cof >= 0);
|
||||
assert(cof == 0 || (order % cof) == 0);
|
||||
Order = order;
|
||||
cofactor = cofactor_short = cof;
|
||||
if (cof > 0) {
|
||||
L = order / cof;
|
||||
assert(is_prime(L));
|
||||
}
|
||||
assert(!power_gen_xz(1).is_infty());
|
||||
assert(power_gen_xz(Order).is_infty());
|
||||
}
|
||||
|
||||
// computes u(P+Q)*u(P-Q) as X/Z
|
||||
MontgomeryCurve::PointXZ MontgomeryCurve::add_xz(const MontgomeryCurve::PointXZ& P,
|
||||
const MontgomeryCurve::PointXZ& Q) const {
|
||||
Residue u = (P.X + P.Z) * (Q.X - Q.Z);
|
||||
Residue v = (P.X - P.Z) * (Q.X + Q.Z);
|
||||
return MontgomeryCurve::PointXZ(sqr(u + v), sqr(u - v));
|
||||
}
|
||||
|
||||
// computes u(2P) as X/Z
|
||||
MontgomeryCurve::PointXZ MontgomeryCurve::double_xz(const MontgomeryCurve::PointXZ& P) const {
|
||||
Residue u = sqr(P.X + P.Z);
|
||||
Residue v = sqr(P.X - P.Z);
|
||||
Residue w = u - v;
|
||||
return PointXZ(u * v, w * (v + Residue(a_short, ring) * w));
|
||||
}
|
||||
|
||||
MontgomeryCurve::PointXZ MontgomeryCurve::power_gen_xz(const Bignum& n) const {
|
||||
return power_xz(Gu, n);
|
||||
}
|
||||
|
||||
MontgomeryCurve::PointXZ MontgomeryCurve::power_xz(const Residue& u, const Bignum& n) const {
|
||||
return power_xz(PointXZ(u), n);
|
||||
}
|
||||
|
||||
// computes u([n]P) in form X/Z
|
||||
MontgomeryCurve::PointXZ MontgomeryCurve::power_xz(const PointXZ& A, const Bignum& n) const {
|
||||
assert(n >= 0);
|
||||
if (n == 0) {
|
||||
return PointXZ(ring);
|
||||
}
|
||||
|
||||
int k = n.num_bits();
|
||||
PointXZ P(A);
|
||||
PointXZ Q(double_xz(P));
|
||||
for (int i = k - 2; i >= 0; --i) {
|
||||
PointXZ PQ(add_xz(P, Q));
|
||||
PQ.X *= A.Z;
|
||||
PQ.Z *= A.X;
|
||||
if (n[i]) {
|
||||
P = PQ;
|
||||
Q = double_xz(Q);
|
||||
} else {
|
||||
Q = PQ;
|
||||
P = double_xz(P);
|
||||
}
|
||||
}
|
||||
return P;
|
||||
}
|
||||
|
||||
bool MontgomeryCurve::PointXZ::export_point_y(unsigned char buffer[32]) const {
|
||||
if ((X + Z).is_zero()) {
|
||||
std::memset(buffer, 0xff, 32);
|
||||
return false;
|
||||
} else {
|
||||
get_y().extract().export_lsb(buffer, 32);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool MontgomeryCurve::PointXZ::export_point_u(unsigned char buffer[32]) const {
|
||||
if (Z.is_zero()) {
|
||||
std::memset(buffer, 0xff, 32);
|
||||
return false;
|
||||
} else {
|
||||
get_u().extract().export_lsb(buffer, 32);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
MontgomeryCurve::PointXZ MontgomeryCurve::import_point_u(const unsigned char point[32]) const {
|
||||
Bignum u;
|
||||
u.import_lsb(point, 32);
|
||||
u[255] = 0;
|
||||
return PointXZ(Residue(u, ring));
|
||||
}
|
||||
|
||||
MontgomeryCurve::PointXZ MontgomeryCurve::import_point_y(const unsigned char point[32]) const {
|
||||
Bignum y;
|
||||
y.import_lsb(point, 32);
|
||||
y[255] = 0;
|
||||
return PointXZ(Residue(y, ring), true);
|
||||
}
|
||||
|
||||
const MontgomeryCurve& Curve25519() {
|
||||
static const MontgomeryCurve Curve25519 = [] {
|
||||
MontgomeryCurve res(486662, 9, Fp25519());
|
||||
res.set_order_cofactor(hex_string{"80000000000000000000000000000000a6f7cef517bce6b2c09318d2e7ae9f68"}, 8);
|
||||
return res;
|
||||
}();
|
||||
return Curve25519;
|
||||
}
|
||||
} // namespace ellcurve
|
123
crypto/ellcurve/Montgomery.h
Normal file
123
crypto/ellcurve/Montgomery.h
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "openssl/bignum.h"
|
||||
#include "openssl/residue.h"
|
||||
#include "ellcurve/Fp25519.h"
|
||||
|
||||
namespace ellcurve {
|
||||
using namespace arith;
|
||||
|
||||
class MontgomeryCurve {
|
||||
td::Ref<ResidueRing> ring;
|
||||
int A_short; // v^2 = u^2 + Au + 1
|
||||
int Gu_short; // u(G)
|
||||
int a_short; // (A+2)/4
|
||||
Residue A_;
|
||||
Residue Gu;
|
||||
Bignum P_;
|
||||
Bignum L;
|
||||
Bignum Order;
|
||||
Bignum cofactor;
|
||||
int cofactor_short;
|
||||
|
||||
void init();
|
||||
|
||||
public:
|
||||
MontgomeryCurve(int _A, int _Gu, td::Ref<ResidueRing> _R)
|
||||
: ring(_R)
|
||||
, A_short(_A)
|
||||
, Gu_short(_Gu)
|
||||
, a_short((_A + 2) / 4)
|
||||
, A_(_A, _R)
|
||||
, Gu(_Gu, _R)
|
||||
, P_(_R->get_modulus())
|
||||
, cofactor_short(0) {
|
||||
init();
|
||||
}
|
||||
|
||||
const Residue& get_gen_u() const {
|
||||
return Gu;
|
||||
}
|
||||
const Bignum& get_ell() const {
|
||||
return L;
|
||||
}
|
||||
const Bignum& get_order() const {
|
||||
return Order;
|
||||
}
|
||||
td::Ref<ResidueRing> get_base_ring() const {
|
||||
return ring;
|
||||
}
|
||||
const Bignum& get_p() const {
|
||||
return P_;
|
||||
}
|
||||
|
||||
void set_order_cofactor(const Bignum& order, int cof);
|
||||
|
||||
struct PointXZ {
|
||||
Residue X, Z;
|
||||
PointXZ(Residue x, Residue z) : X(x), Z(z) {
|
||||
x.same_ring(z);
|
||||
}
|
||||
PointXZ(td::Ref<ResidueRing> r) : X(r->one()), Z(r->zero()) {
|
||||
}
|
||||
explicit PointXZ(Residue u) : X(u), Z(u.ring_of().one()) {
|
||||
}
|
||||
explicit PointXZ(Residue y, bool) : X(y.ring_of().one() + y), Z(y.ring_of().one() - y) {
|
||||
}
|
||||
PointXZ(const PointXZ& P) : X(P.X), Z(P.Z) {
|
||||
}
|
||||
PointXZ& operator=(const PointXZ& P) {
|
||||
X = P.X;
|
||||
Z = P.Z;
|
||||
return *this;
|
||||
}
|
||||
Residue get_u() const {
|
||||
return X * inverse(Z);
|
||||
}
|
||||
Residue get_v(bool sign_v = false) const;
|
||||
bool is_infty() const {
|
||||
return Z.is_zero();
|
||||
}
|
||||
Residue get_y() const {
|
||||
return (X - Z) * inverse(X + Z);
|
||||
}
|
||||
bool export_point_y(unsigned char buffer[32]) const;
|
||||
bool export_point_u(unsigned char buffer[32]) const;
|
||||
void zeroize() {
|
||||
X = Z = Z.ring_of().zero();
|
||||
}
|
||||
};
|
||||
|
||||
PointXZ power_gen_xz(const Bignum& n) const;
|
||||
PointXZ power_xz(const Residue& u, const Bignum& n) const;
|
||||
PointXZ power_xz(const PointXZ& P, const Bignum& n) const;
|
||||
PointXZ add_xz(const PointXZ& P, const PointXZ& Q) const;
|
||||
PointXZ double_xz(const PointXZ& P) const;
|
||||
|
||||
PointXZ import_point_u(const unsigned char point[32]) const;
|
||||
PointXZ import_point_y(const unsigned char point[32]) const;
|
||||
};
|
||||
|
||||
const MontgomeryCurve& Curve25519();
|
||||
|
||||
} // namespace ellcurve
|
255
crypto/ellcurve/TwEdwards.cpp
Normal file
255
crypto/ellcurve/TwEdwards.cpp
Normal file
|
@ -0,0 +1,255 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
#include "ellcurve/TwEdwards.h"
|
||||
#include <assert.h>
|
||||
#include <cstring>
|
||||
|
||||
namespace ellcurve {
|
||||
using namespace arith;
|
||||
|
||||
class TwEdwardsCurve;
|
||||
|
||||
TwEdwardsCurve::TwEdwardsCurve(const Residue& _D, const Residue& _Gy, td::Ref<ResidueRing> _R)
|
||||
: ring(_R)
|
||||
, D(_D)
|
||||
, D2(_D + _D)
|
||||
, Gy(_Gy)
|
||||
, P_(_R->get_modulus())
|
||||
, cofactor_short(0)
|
||||
, G(_R)
|
||||
, O(_R)
|
||||
, table_lines(0)
|
||||
, table() {
|
||||
init();
|
||||
}
|
||||
|
||||
TwEdwardsCurve::~TwEdwardsCurve() {
|
||||
}
|
||||
|
||||
void TwEdwardsCurve::init() {
|
||||
assert(D != ring->zero() && D != ring->convert(-1));
|
||||
O.X = O.Z = ring->one();
|
||||
G = SegrePoint(*this, Gy, 0);
|
||||
assert(!G.XY.is_zero());
|
||||
}
|
||||
|
||||
void TwEdwardsCurve::set_order_cofactor(const Bignum& order, int cof) {
|
||||
assert(order > 0);
|
||||
assert(cof >= 0);
|
||||
assert(cof == 0 || (order % cof) == 0);
|
||||
Order = order;
|
||||
cofactor = cofactor_short = cof;
|
||||
if (cof > 0) {
|
||||
L = order / cof;
|
||||
assert(is_prime(L));
|
||||
assert(!power_gen(1).is_zero());
|
||||
assert(power_gen(L).is_zero());
|
||||
}
|
||||
}
|
||||
|
||||
TwEdwardsCurve::SegrePoint::SegrePoint(const TwEdwardsCurve& E, const Residue& y, bool x_sign)
|
||||
: XY(y), X(E.get_base_ring()), Y(y), Z(E.get_base_ring()->one()) {
|
||||
Residue x(y.ring_ref());
|
||||
if (E.recover_x(x, y, x_sign)) {
|
||||
XY *= x;
|
||||
X = x;
|
||||
} else {
|
||||
XY = Y = Z = E.get_base_ring()->zero();
|
||||
}
|
||||
}
|
||||
|
||||
bool TwEdwardsCurve::recover_x(Residue& x, const Residue& y, bool x_sign) const {
|
||||
// recovers x from equation -x^2+y^2 = 1+d*x^2*y^2
|
||||
Residue z = inverse(ring->one() + D * sqr(y));
|
||||
if (z.is_zero()) {
|
||||
return false;
|
||||
}
|
||||
z *= sqr(y) - ring->one();
|
||||
Residue t = sqrt(z);
|
||||
if (sqr(t) == z) {
|
||||
x = (t.extract().odd() == x_sign) ? t : -t;
|
||||
//std::cout << "x=" << x << ", y=" << y << std::endl;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void TwEdwardsCurve::add_points(SegrePoint& Res, const SegrePoint& P, const SegrePoint& Q) const {
|
||||
Residue a((P.X + P.Y) * (Q.X + Q.Y));
|
||||
Residue b((P.X - P.Y) * (Q.X - Q.Y));
|
||||
Residue c(P.Z * Q.Z * ring->convert(2));
|
||||
Residue d(P.XY * Q.XY * D2);
|
||||
Residue x_num(a - b); // 2(x1y2+x2y1)
|
||||
Residue y_num(a + b); // 2(x1x2+y1y2)
|
||||
Residue x_den(c + d); // 2(1+dx1x2y1y2)
|
||||
Residue y_den(c - d); // 2(1-dx1x2y1y2)
|
||||
Res.X = x_num * y_den; // x = x_num/x_den, y = y_num/y_den
|
||||
Res.Y = y_num * x_den;
|
||||
Res.XY = x_num * y_num;
|
||||
Res.Z = x_den * y_den;
|
||||
}
|
||||
|
||||
TwEdwardsCurve::SegrePoint TwEdwardsCurve::add_points(const SegrePoint& P, const SegrePoint& Q) const {
|
||||
SegrePoint Res(ring);
|
||||
add_points(Res, P, Q);
|
||||
return Res;
|
||||
}
|
||||
|
||||
void TwEdwardsCurve::double_point(SegrePoint& Res, const SegrePoint& P) const {
|
||||
add_points(Res, P, P);
|
||||
}
|
||||
|
||||
TwEdwardsCurve::SegrePoint TwEdwardsCurve::double_point(const SegrePoint& P) const {
|
||||
SegrePoint Res(ring);
|
||||
double_point(Res, P);
|
||||
return Res;
|
||||
}
|
||||
|
||||
// computes u([n]P) in form (xy,x,y,1)*Z
|
||||
TwEdwardsCurve::SegrePoint TwEdwardsCurve::power_point(const SegrePoint& A, const Bignum& n, bool uniform) const {
|
||||
assert(n >= 0);
|
||||
if (n == 0) {
|
||||
return O;
|
||||
}
|
||||
|
||||
int k = n.num_bits();
|
||||
SegrePoint P(A);
|
||||
|
||||
if (uniform) {
|
||||
SegrePoint Q(double_point(A));
|
||||
|
||||
for (int i = k - 2; i >= 0; --i) {
|
||||
if (n[i]) {
|
||||
add_points(P, P, Q);
|
||||
double_point(Q, Q);
|
||||
} else {
|
||||
// we do more operations than necessary for uniformicity
|
||||
add_points(Q, P, Q);
|
||||
double_point(P, P);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = k - 2; i >= 0; --i) {
|
||||
double_point(P, P);
|
||||
if (n[i]) {
|
||||
add_points(P, P, A); // may optimize further if A.z = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
return P;
|
||||
}
|
||||
|
||||
int TwEdwardsCurve::build_table() {
|
||||
if (table.size()) {
|
||||
return -1;
|
||||
}
|
||||
table_lines = (P_.num_bits() >> 2) + 2;
|
||||
table.reserve(table_lines * 15 + 1);
|
||||
table.emplace_back(get_base_point());
|
||||
for (int i = 0; i < table_lines; i++) {
|
||||
for (int j = 0; j < 15; j++) {
|
||||
table.emplace_back(add_points(table[15 * i + j], table[15 * i]));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int get_nibble(const Bignum& n, int idx) {
|
||||
return n[idx * 4 + 3] * 8 + n[idx * 4 + 2] * 4 + n[idx * 4 + 1] * 2 + n[idx * 4];
|
||||
}
|
||||
|
||||
TwEdwardsCurve::SegrePoint TwEdwardsCurve::power_gen(const Bignum& n, bool uniform) const {
|
||||
if (uniform || n.num_bits() > table_lines * 4) {
|
||||
return power_point(G, n, uniform);
|
||||
} else if (n.is_zero()) {
|
||||
return O;
|
||||
} else {
|
||||
int k = (n.num_bits() + 3) >> 2;
|
||||
assert(k > 0 && k <= table_lines);
|
||||
int x = get_nibble(n, k - 1);
|
||||
assert(x > 0 && x < 16);
|
||||
SegrePoint P(table[15 * (k - 1) + x - 1]);
|
||||
for (int i = k - 2; i >= 0; i--) {
|
||||
x = get_nibble(n, i);
|
||||
assert(x >= 0 && x < 16);
|
||||
if (x > 0) {
|
||||
add_points(P, P, table[15 * i + x - 1]);
|
||||
}
|
||||
}
|
||||
return P;
|
||||
}
|
||||
}
|
||||
|
||||
bool TwEdwardsCurve::SegrePoint::export_point(unsigned char buffer[32], bool need_x) const {
|
||||
if (!is_normalized()) {
|
||||
if (Z.is_zero()) {
|
||||
std::memset(buffer, 0xff, 32);
|
||||
return false;
|
||||
}
|
||||
Residue f(inverse(Z));
|
||||
Bignum y((Y * f).extract());
|
||||
assert(!y[255]);
|
||||
if (need_x) {
|
||||
y[255] = (X * f).extract().odd();
|
||||
}
|
||||
y.export_lsb(buffer, 32);
|
||||
} else {
|
||||
Bignum y(Y.extract());
|
||||
assert(!y[255]);
|
||||
if (need_x) {
|
||||
y[255] = X.extract().odd();
|
||||
}
|
||||
y.export_lsb(buffer, 32);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TwEdwardsCurve::SegrePoint::export_point_u(unsigned char buffer[32]) const {
|
||||
if (Z == Y) {
|
||||
std::memset(buffer, 0xff, 32);
|
||||
return false;
|
||||
}
|
||||
Residue f(inverse(Z - Y));
|
||||
((Z + Y) * f).extract().export_lsb(buffer, 32);
|
||||
assert(!(buffer[31] & 0x80));
|
||||
return true;
|
||||
}
|
||||
|
||||
TwEdwardsCurve::SegrePoint TwEdwardsCurve::import_point(const unsigned char point[32], bool& ok) const {
|
||||
Bignum y;
|
||||
y.import_lsb(point, 32);
|
||||
bool x_sign = y[255];
|
||||
y[255] = 0;
|
||||
Residue yr(y, ring);
|
||||
Residue xr(ring);
|
||||
ok = recover_x(xr, yr, x_sign);
|
||||
return ok ? SegrePoint(xr, yr) : SegrePoint(ring);
|
||||
}
|
||||
|
||||
const TwEdwardsCurve& Ed25519() {
|
||||
static const TwEdwardsCurve Ed25519 = [] {
|
||||
TwEdwardsCurve res(Fp25519()->frac(-121665, 121666), Fp25519()->frac(4, 5), Fp25519());
|
||||
res.set_order_cofactor(hex_string{"80000000000000000000000000000000a6f7cef517bce6b2c09318d2e7ae9f68"}, 8);
|
||||
res.build_table();
|
||||
return res;
|
||||
}();
|
||||
return Ed25519;
|
||||
}
|
||||
} // namespace ellcurve
|
145
crypto/ellcurve/TwEdwards.h
Normal file
145
crypto/ellcurve/TwEdwards.h
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
This file is part of TON Blockchain Library.
|
||||
|
||||
TON Blockchain Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
TON Blockchain Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with TON Blockchain Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2017-2019 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include "common/refcnt.hpp"
|
||||
#include "openssl/residue.h"
|
||||
#include "ellcurve/Fp25519.h"
|
||||
|
||||
namespace ellcurve {
|
||||
using namespace arith;
|
||||
|
||||
class TwEdwardsCurve {
|
||||
public:
|
||||
struct SegrePoint {
|
||||
Residue XY, X, Y, Z; // if x=X/Z and y=Y/T, stores (xy,x,y,1)*Z*T
|
||||
SegrePoint(td::Ref<ResidueRing> R) : XY(R), X(R), Y(R), Z(R) {
|
||||
}
|
||||
SegrePoint(const Residue& x, const Residue& y) : XY(x * y), X(x), Y(y), Z(y.ring_of().one()) {
|
||||
}
|
||||
SegrePoint(const TwEdwardsCurve& E, const Residue& y, bool x_sign);
|
||||
SegrePoint(const SegrePoint& P) : XY(P.XY), X(P.X), Y(P.Y), Z(P.Z) {
|
||||
}
|
||||
SegrePoint& operator=(const SegrePoint& P) {
|
||||
XY = P.XY;
|
||||
X = P.X;
|
||||
Y = P.Y;
|
||||
Z = P.Z;
|
||||
return *this;
|
||||
}
|
||||
bool is_zero() const {
|
||||
return X.is_zero() && (Y == Z);
|
||||
}
|
||||
bool is_valid() const {
|
||||
return (XY * Z == X * Y) && !(XY.is_zero() && X.is_zero() && Y.is_zero() && Z.is_zero());
|
||||
}
|
||||
bool is_finite() const {
|
||||
return !Z.is_zero();
|
||||
}
|
||||
bool is_normalized() const {
|
||||
return Z == Z.ring_of().one();
|
||||
}
|
||||
SegrePoint& normalize() {
|
||||
auto f = inverse(Z);
|
||||
XY *= f;
|
||||
X *= f;
|
||||
Y *= f;
|
||||
Z = Z.ring_of().one();
|
||||
return *this;
|
||||
}
|
||||
SegrePoint& zeroize() {
|
||||
XY = X = Y = Z = Z.ring_of().zero();
|
||||
return *this;
|
||||
}
|
||||
bool export_point(unsigned char buffer[32], bool need_x = true) const;
|
||||
bool export_point_y(unsigned char buffer[32]) const {
|
||||
return export_point(buffer, false);
|
||||
}
|
||||
bool export_point_u(unsigned char buffer[32]) const;
|
||||
Residue get_y() const {
|
||||
return Y * inverse(Z);
|
||||
}
|
||||
Residue get_x() const {
|
||||
return X * inverse(Z);
|
||||
}
|
||||
Residue get_u() const {
|
||||
return (Z + Y) * inverse(Z - Y);
|
||||
}
|
||||
void negate() {
|
||||
XY.negate();
|
||||
X.negate();
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
td::Ref<ResidueRing> ring;
|
||||
Residue D;
|
||||
Residue D2;
|
||||
Residue Gy;
|
||||
Bignum P_;
|
||||
Bignum L;
|
||||
Bignum Order;
|
||||
Bignum cofactor;
|
||||
int cofactor_short;
|
||||
SegrePoint G;
|
||||
SegrePoint O;
|
||||
int table_lines;
|
||||
std::vector<SegrePoint> table;
|
||||
|
||||
void init();
|
||||
|
||||
public:
|
||||
TwEdwardsCurve(const Residue& _D, const Residue& _Gy, td::Ref<ResidueRing> _R);
|
||||
~TwEdwardsCurve();
|
||||
const Residue& get_gen_y() const {
|
||||
return Gy;
|
||||
}
|
||||
const Bignum& get_ell() const {
|
||||
return L;
|
||||
}
|
||||
const Bignum& get_order() const {
|
||||
return Order;
|
||||
}
|
||||
td::Ref<ResidueRing> get_base_ring() const {
|
||||
return ring;
|
||||
}
|
||||
const Bignum& get_p() const {
|
||||
return P_;
|
||||
}
|
||||
const SegrePoint& get_base_point() const {
|
||||
return G;
|
||||
}
|
||||
|
||||
void set_order_cofactor(const Bignum& order, int cof);
|
||||
bool recover_x(Residue& x, const Residue& y, bool x_sign) const;
|
||||
|
||||
void add_points(SegrePoint& R, const SegrePoint& P, const SegrePoint& Q) const;
|
||||
SegrePoint add_points(const SegrePoint& P, const SegrePoint& Q) const;
|
||||
void double_point(SegrePoint& R, const SegrePoint& P) const;
|
||||
SegrePoint double_point(const SegrePoint& P) const;
|
||||
SegrePoint power_point(const SegrePoint& A, const Bignum& n, bool uniform = false) const;
|
||||
SegrePoint power_gen(const Bignum& n, bool uniform = false) const;
|
||||
int build_table();
|
||||
|
||||
SegrePoint import_point(const unsigned char point[32], bool& ok) const;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const TwEdwardsCurve::SegrePoint& P);
|
||||
const TwEdwardsCurve& Ed25519();
|
||||
} // namespace ellcurve
|
Loading…
Add table
Add a link
Reference in a new issue