#include <openssl/obj_mac.h>
#include "key.h"
+#include "base58.h"
// Generate a private key from just the secret parameter
int EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
key2.SetSecret(secret, fCompr);
return GetPubKey() == key2.GetPubKey();
}
+
+CPoint::CPoint()
+{
+ std::string err;
+ group = NULL;
+ point = NULL;
+ ctx = NULL;
+
+ group = EC_GROUP_new_by_curve_name(NID_secp256k1);
+ if (!group) {
+ err = "EC_KEY_new_by_curve_name failed.";
+ goto finish;
+ }
+
+ point = EC_POINT_new(group);
+ if (!point) {
+ err = "EC_POINT_new failed.";
+ goto finish;
+ }
+
+ ctx = BN_CTX_new();
+ if (!ctx) {
+ err = "BN_CTX_new failed.";
+ goto finish;
+ }
+
+ return;
+
+finish:
+ if (group) EC_GROUP_free(group);
+ if (point) EC_POINT_free(point);
+ throw std::runtime_error(std::string("CPoint::CPoint() : - ") + err);
+}
+
+bool CPoint::operator!=(const CPoint &a)
+{
+ if (EC_POINT_cmp(group, point, a.point, ctx) != 0)
+ return true;
+ return false;
+}
+CPoint::~CPoint()
+{
+ if (point) EC_POINT_free(point);
+ if (group) EC_GROUP_free(group);
+ if (ctx) BN_CTX_free(ctx);
+}
+
+// Initialize from octets stream
+bool CPoint::setBytes(const std::vector<unsigned char> &vchBytes)
+{
+ if (!EC_POINT_oct2point(group, point, &vchBytes[0], vchBytes.size(), ctx)) {
+ return false;
+ }
+ return true;
+}
+
+// Serialize to octets stream
+bool CPoint::getBytes(std::vector<unsigned char> &vchBytes)
+{
+ unsigned int nSize = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, NULL, 0, ctx);
+ vchBytes.resize(nSize);
+ if (!(nSize == EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, &vchBytes[0], nSize, ctx))) {
+ return false;
+ }
+ return true;
+}
+
+// ECC multiplication by specified multiplier
+bool CPoint::ECMUL(const CBigNum &bnMultiplier)
+{
+ if (!EC_POINT_mul(group, point, NULL, point, &bnMultiplier, NULL)) {
+ printf("CPoint::ECMUL() : EC_POINT_mul failed");
+ return false;
+ }
+
+ return true;
+}
+
+// Calculate G*m + q
+bool CPoint::ECMULGEN(const CBigNum &bnMultiplier, const CPoint &qPoint)
+{
+ if (!EC_POINT_mul(group, point, &bnMultiplier, qPoint.point, BN_value_one(), NULL)) {
+ printf("CPoint::ECMULGEN() : EC_POINT_mul failed.");
+ return false;
+ }
+
+ return true;
+}
+
+// CMalleablePubKey
+
+void CMalleablePubKey::GetVariant(CPubKey &R, CPubKey &vchPubKeyVariant)
+{
+ EC_KEY *eckey = NULL;
+ eckey = EC_KEY_new_by_curve_name(NID_secp256k1);
+ if (eckey == NULL) {
+ throw key_error("CMalleablePubKey::GetVariant() : EC_KEY_new_by_curve_name failed");
+ }
+
+ // Use standard key generation function to get r and R values.
+ //
+ // r will be presented by private key;
+ // R is ECDSA public key which calculated as G*r
+ if (!EC_KEY_generate_key(eckey)) {
+ throw key_error("CMalleablePubKey::GetVariant() : EC_KEY_generate_key failed");
+ }
+
+ EC_KEY_set_conv_form(eckey, POINT_CONVERSION_COMPRESSED);
+
+ int nSize = i2o_ECPublicKey(eckey, NULL);
+ if (!nSize) {
+ throw key_error("CMalleablePubKey::GetVariant() : i2o_ECPublicKey failed");
+ }
+
+ std::vector<unsigned char> vchPubKey(nSize, 0);
+ unsigned char* pbegin_R = &vchPubKey[0];
+
+ if (i2o_ECPublicKey(eckey, &pbegin_R) != nSize) {
+ throw key_error("CMalleablePubKey::GetVariant() : i2o_ECPublicKey returned unexpected size");
+ }
+
+ // R = G*r
+ R = CPubKey(vchPubKey);
+
+ // OpenSSL BIGNUM representation of r value
+ CBigNum bnr;
+ bnr = *(CBigNum*) EC_KEY_get0_private_key(eckey);
+ EC_KEY_free(eckey);
+
+ CPoint point;
+ if (!point.setBytes(pubKeyL.Raw())) {
+ throw key_error("CMalleablePubKey::GetVariant() : Unable to decode L value");
+ }
+
+ // Calculate L*r
+ point.ECMUL(bnr);
+
+ std::vector<unsigned char> vchLr;
+ if (!point.getBytes(vchLr)) {
+ throw key_error("CMalleablePubKey::GetVariant() : Unable to convert Lr value");
+ }
+
+ // Calculate Hash(L*r) and then get a BIGNUM representation of hash value.
+ CBigNum bnHash;
+ bnHash.setuint160(Hash160(vchLr));
+
+ CPoint pointH;
+ pointH.setBytes(pubKeyH.Raw());
+
+ CPoint P;
+ // Calculate P = Hash(L*r)*G + H
+ P.ECMULGEN(bnHash, pointH);
+
+ if (P.IsInfinity()) {
+ throw key_error("CMalleablePubKey::GetVariant() : P is infinity");
+ }
+
+ std::vector<unsigned char> vchResult;
+ P.getBytes(vchResult);
+
+ vchPubKeyVariant = CPubKey(vchResult);
+}
+
+std::string CMalleablePubKey::ToString()
+{
+ CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
+ ssKey << *this;
+ std::vector<unsigned char> vch(ssKey.begin(), ssKey.end());
+
+ return EncodeBase58Check(vch);
+}
+
+bool CMalleablePubKey::SetString(const std::string& strMalleablePubKey)
+{
+ std::vector<unsigned char> vchTemp;
+ if (!DecodeBase58Check(strMalleablePubKey, vchTemp)) {
+ throw key_error("CMalleablePubKey::SetString() : Provided key data seems corrupted.");
+ }
+
+ CDataStream ssKey(vchTemp, SER_NETWORK, PROTOCOL_VERSION);
+ ssKey >> *this;
+
+ return IsValid();
+}
+
+bool CMalleablePubKey::operator==(const CMalleablePubKey &b)
+{
+ return (nVersion == b.nVersion &&
+ pubKeyL == b.pubKeyL &&
+ pubKeyH == b.pubKeyH);
+}
+
+
+// CMalleableKey
+
+void CMalleableKey::Reset()
+{
+ vchSecretL.clear();
+ vchSecretH.clear();
+
+ nVersion = 0;
+}
+
+void CMalleableKey::MakeNewKeys()
+{
+ CKey L, H;
+ bool fCompressed = true;
+
+ L.MakeNewKey(true);
+ H.MakeNewKey(true);
+
+ vchSecretL = L.GetSecret(fCompressed);
+ vchSecretH = H.GetSecret(fCompressed);
+
+ nVersion = CURRENT_VERSION;
+}
+
+CMalleableKey::CMalleableKey()
+{
+ Reset();
+}
+
+CMalleableKey::CMalleableKey(const CMalleableKey &b)
+{
+ SetSecrets(b.vchSecretL, b.vchSecretH);
+}
+
+CMalleableKey::CMalleableKey(const CSecret &L, const CSecret &H)
+{
+ SetSecrets(L, H);
+}
+
+CMalleableKey& CMalleableKey::operator=(const CMalleableKey &b)
+{
+ SetSecrets(b.vchSecretL, b.vchSecretH);
+
+ return (*this);
+}
+
+CMalleableKey::~CMalleableKey()
+{
+}
+
+bool CMalleableKey::IsNull() const
+{
+ return nVersion != CURRENT_VERSION;
+}
+
+bool CMalleableKey::SetSecrets(const CSecret &pvchSecretL, const CSecret &pvchSecretH)
+{
+ Reset();
+ CKey L, H;
+
+ if (!L.SetSecret(pvchSecretL, true) || !H.SetSecret(pvchSecretH, true))
+ {
+ nVersion = 0;
+ return false;
+ }
+
+ vchSecretL = pvchSecretL;
+ vchSecretH = pvchSecretH;
+ nVersion = CURRENT_VERSION;
+
+ return true;
+}
+
+void CMalleableKey::GetSecrets(CSecret &pvchSecretL, CSecret &pvchSecretH) const
+{
+ pvchSecretL = vchSecretL;
+ pvchSecretH = vchSecretH;
+}
+
+CMalleablePubKey CMalleableKey::GetMalleablePubKey() const
+{
+ CKey L, H;
+ L.SetSecret(vchSecretL, true);
+ H.SetSecret(vchSecretH, true);
+
+ std::vector<unsigned char> vchPubKeyL = L.GetPubKey().Raw();
+ std::vector<unsigned char> vchPubKeyH = H.GetPubKey().Raw();
+
+ return CMalleablePubKey(vchPubKeyL, vchPubKeyH);
+}
+
+// Check ownership
+bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant)
+{
+ if (IsNull()) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : Attempting to run on NULL key object.");
+ }
+
+ if (!R.IsValid()) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : R is invalid");
+ }
+
+ if (!vchPubKeyVariant.IsValid()) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : public key variant is invalid");
+ }
+
+ CPoint point_R;
+ if (!point_R.setBytes(R.Raw())) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : Unable to decode R value");
+ }
+
+ CKey H;
+ H.SetSecret(vchSecretH, true);
+ std::vector<unsigned char> vchPubKeyH = H.GetPubKey().Raw();
+
+ CPoint point_H;
+ if (!point_H.setBytes(vchPubKeyH)) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : Unable to decode H value");
+ }
+
+ CPoint point_P;
+ if (!point_P.setBytes(vchPubKeyVariant.Raw())) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : Unable to decode P value");
+ }
+
+ // Infinity points are senseless
+ if (point_P.IsInfinity()) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : P is infinity");
+ }
+
+ CBigNum bnl;
+ bnl.setBytes(std::vector<unsigned char>(vchSecretL.begin(), vchSecretL.end()));
+
+ point_R.ECMUL(bnl);
+
+ std::vector<unsigned char> vchRl;
+ if (!point_R.getBytes(vchRl)) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : Unable to convert Rl value");
+ }
+
+ // Calculate Hash(R*l)
+ CBigNum bnHash;
+ bnHash.setuint160(Hash160(vchRl));
+
+ CPoint point_Ps;
+ // Calculate Ps = Hash(L*r)*G + H
+ point_Ps.ECMULGEN(bnHash, point_H);
+
+ // Infinity points are senseless
+ if (point_Ps.IsInfinity()) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : Ps is infinity");
+ }
+
+ // Check ownership
+ if (point_Ps != point_P) {
+ return false;
+ }
+
+ return true;
+}
+
+// Check ownership and restore private key
+bool CMalleableKey::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant, CKey &privKeyVariant)
+{
+ if (IsNull()) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : Attempting to run on NULL key object.");
+ }
+
+ if (!R.IsValid()) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : R is invalid");
+ }
+
+ if (!vchPubKeyVariant.IsValid()) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : public key variant is invalid");
+ }
+
+ CPoint point_R;
+ if (!point_R.setBytes(R.Raw())) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : Unable to decode R value");
+ }
+
+ CKey H;
+ H.SetSecret(vchSecretH, true);
+ std::vector<unsigned char> vchPubKeyH = H.GetPubKey().Raw();
+
+ CPoint point_H;
+ if (!point_H.setBytes(vchPubKeyH)) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : Unable to decode H value");
+ }
+
+ CPoint point_P;
+ if (!point_P.setBytes(vchPubKeyVariant.Raw())) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : Unable to decode P value");
+ }
+
+ // Infinity points are senseless
+ if (point_P.IsInfinity()) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : P is infinity");
+ }
+
+ CBigNum bnl;
+ bnl.setBytes(std::vector<unsigned char>(vchSecretL.begin(), vchSecretL.end()));
+
+ point_R.ECMUL(bnl);
+
+ std::vector<unsigned char> vchRl;
+ if (!point_R.getBytes(vchRl)) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : Unable to convert Rl value");
+ }
+
+ // Calculate Hash(R*l)
+ CBigNum bnHash;
+ bnHash.setuint160(Hash160(vchRl));
+
+ CPoint point_Ps;
+ // Calculate Ps = Hash(L*r)*G + H
+ point_Ps.ECMULGEN(bnHash, point_H);
+
+ // Infinity points are senseless
+ if (point_Ps.IsInfinity()) {
+ throw key_error("CMalleableKey::CheckKeyVariant() : Ps is infinity");
+ }
+
+ // Check ownership
+ if (point_Ps != point_P) {
+ return false;
+ }
+
+ // OpenSSL BIGNUM representation of the second private key from (l, h) pair
+ CBigNum bnh;
+ bnh.setBytes(std::vector<unsigned char>(vchSecretH.begin(), vchSecretH.end()));
+
+ // Calculate p = Hash(R*l) + h
+ CBigNum bnp = bnHash + bnh;
+
+ std::vector<unsigned char> vchp = bnp.getBytes();
+ privKeyVariant.SetSecret(CSecret(vchp.begin(), vchp.end()), true);
+
+ return true;
+}
+
+std::string CMalleableKey::ToString()
+{
+ CDataStream ssKey(SER_NETWORK, PROTOCOL_VERSION);
+ ssKey << *this;
+ std::vector<unsigned char> vch(ssKey.begin(), ssKey.end());
+
+ return EncodeBase58Check(vch);
+}
+
+bool CMalleableKey::SetString(const std::string& strMutableKey)
+{
+ std::vector<unsigned char> vchTemp;
+ if (!DecodeBase58Check(strMutableKey, vchTemp)) {
+ throw key_error("CMalleableKey::SetString() : Provided key data seems corrupted.");
+ }
+
+ CDataStream ssKey(vchTemp, SER_NETWORK, PROTOCOL_VERSION);
+ ssKey >> *this;
+
+ return IsNull();
+}
+
+// CMalleableKeyView
+
+CMalleableKeyView::CMalleableKeyView(const CMalleableKey &b)
+{
+ assert(b.nVersion == CURRENT_VERSION);
+ vchSecretL = b.vchSecretL;
+
+ CKey H;
+ H.SetSecret(b.vchSecretH, true);
+ vchPubKeyH = H.GetPubKey().Raw();
+}
+
+CMalleableKeyView::CMalleableKeyView(const CSecret &L, const CPubKey &pvchPubKeyH)
+{
+ vchSecretL = L;
+ vchPubKeyH = pvchPubKeyH.Raw();
+}
+
+CMalleableKeyView& CMalleableKeyView::operator=(const CMalleableKey &b)
+{
+ assert(b.nVersion == CURRENT_VERSION);
+ vchSecretL = b.vchSecretL;
+
+ CKey H;
+ H.SetSecret(b.vchSecretH, true);
+ vchPubKeyH = H.GetPubKey().Raw();
+
+ return (*this);
+}
+
+CMalleableKeyView::~CMalleableKeyView()
+{
+}
+
+CMalleablePubKey CMalleableKeyView::GetMalleablePubKey() const
+{
+ CKey keyL;
+ keyL.SetSecret(vchSecretL, true);
+ return CMalleablePubKey(keyL.GetPubKey(), vchPubKeyH);
+}
+
+// Check ownership
+bool CMalleableKeyView::CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant)
+{
+ if (!R.IsValid()) {
+ throw key_error("CMalleableKeyView::CheckKeyVariant() : R is invalid");
+ }
+
+ if (!vchPubKeyVariant.IsValid()) {
+ throw key_error("CMalleableKeyView::CheckKeyVariant() : public key variant is invalid");
+ }
+
+ CPoint point_R;
+ if (!point_R.setBytes(R.Raw())) {
+ throw key_error("CMalleableKeyView::CheckKeyVariant() : Unable to decode R value");
+ }
+
+ CPoint point_H;
+ if (!point_H.setBytes(vchPubKeyH)) {
+ throw key_error("CMalleableKeyView::CheckKeyVariant() : Unable to decode H value");
+ }
+
+ CPoint point_P;
+ if (!point_P.setBytes(vchPubKeyVariant.Raw())) {
+ throw key_error("CMalleableKeyView::CheckKeyVariant() : Unable to decode P value");
+ }
+
+ // Infinity points are senseless
+ if (point_P.IsInfinity()) {
+ throw key_error("CMalleableKeyView::CheckKeyVariant() : P is infinity");
+ }
+
+ CBigNum bnl;
+ bnl.setBytes(std::vector<unsigned char>(vchSecretL.begin(), vchSecretL.end()));
+
+ point_R.ECMUL(bnl);
+
+ std::vector<unsigned char> vchRl;
+ if (!point_R.getBytes(vchRl)) {
+ throw key_error("CMalleableKeyView::CheckKeyVariant() : Unable to convert Rl value");
+ }
+
+ // Calculate Hash(R*l)
+ CBigNum bnHash;
+ bnHash.setuint160(Hash160(vchRl));
+
+ CPoint point_Ps;
+ // Calculate Ps = Hash(L*r)*G + H
+ point_Ps.ECMULGEN(bnHash, point_H);
+
+ // Infinity points are senseless
+ if (point_Ps.IsInfinity()) {
+ throw key_error("CMalleableKeyView::CheckKeyVariant() : Ps is infinity");
+ }
+
+ // Check ownership
+ if (point_Ps != point_P) {
+ return false;
+ }
+
+ return true;
+}
+
static bool ReserealizeSignature(std::vector<unsigned char>& vchSig);
};
+class CPoint
+{
+private:
+ EC_POINT *point;
+ EC_GROUP* group;
+ BN_CTX* ctx;
+
+public:
+ CPoint();
+ bool operator!=(const CPoint &a);
+ ~CPoint();
+
+ // Initialize from octets stream
+ bool setBytes(const std::vector<unsigned char> &vchBytes);
+
+ // Serialize to octets stream
+ bool getBytes(std::vector<unsigned char> &vchBytes);
+
+ // ECC multiplication by specified multiplier
+ bool ECMUL(const CBigNum &bnMultiplier);
+
+ // Calculate G*m + q
+ bool ECMULGEN(const CBigNum &bnMultiplier, const CPoint &qPoint);
+
+ bool IsInfinity() { return EC_POINT_is_at_infinity(group, point); }
+};
+
+class CMalleablePubKey
+{
+private:
+ unsigned char nVersion;
+ CPubKey pubKeyL;
+ CPubKey pubKeyH;
+ friend class CMalleableKey;
+
+ static const unsigned char CURRENT_VERSION = 1;
+
+public:
+ CMalleablePubKey() { nVersion = CMalleablePubKey::CURRENT_VERSION; }
+ CMalleablePubKey(const std::string& strMalleablePubKey) { SetString(strMalleablePubKey); }
+ CMalleablePubKey(const CPubKey &pubKeyInL, const CPubKey &pubKeyInH) : pubKeyL(pubKeyInL), pubKeyH(pubKeyInH) { nVersion = CMalleablePubKey::CURRENT_VERSION; }
+ CMalleablePubKey(const std::vector<unsigned char> &pubKeyInL, const std::vector<unsigned char> &pubKeyInH) : pubKeyL(pubKeyInL), pubKeyH(pubKeyInH) { nVersion = CMalleablePubKey::CURRENT_VERSION; }
+
+ IMPLEMENT_SERIALIZE(
+ READWRITE(this->nVersion);
+ nVersion = this->nVersion;
+ READWRITE(pubKeyL);
+ READWRITE(pubKeyH);
+ )
+
+ bool IsValid() const {
+ return pubKeyL.IsValid() && pubKeyH.IsValid();
+ }
+
+ bool operator==(const CMalleablePubKey &b);
+ bool operator!=(const CMalleablePubKey &b) { return !(*this == b); }
+
+ std::string ToString();
+ bool SetString(const std::string& strMalleablePubKey);
+ uint256 GetID() const;
+
+ CPubKey& GetL() { return pubKeyL; }
+ CPubKey& GetH() { return pubKeyH; }
+ void GetVariant(CPubKey &R, CPubKey &vchPubKeyVariant);
+};
+
+class CMalleableKey
+{
+private:
+ unsigned char nVersion;
+ CSecret vchSecretL;
+ CSecret vchSecretH;
+
+ friend class CMalleableKeyView;
+
+ static const unsigned char CURRENT_VERSION = 1;
+
+public:
+ CMalleableKey();
+ CMalleableKey(const CMalleableKey &b);
+ CMalleableKey(const CSecret &L, const CSecret &H);
+ CMalleableKey& operator=(const CMalleableKey &b);
+ ~CMalleableKey();
+
+ IMPLEMENT_SERIALIZE(
+ READWRITE(this->nVersion);
+ nVersion = this->nVersion;
+ READWRITE(vchSecretL);
+ READWRITE(vchSecretH);
+ )
+
+ std::string ToString();
+ bool SetString(const std::string& strMalleablePubKey);
+
+ void Reset();
+ void MakeNewKeys();
+ bool IsNull() const;
+ bool SetSecrets(const CSecret &pvchSecretL, const CSecret &pvchSecretH);
+ void GetSecrets(CSecret &pvchSecretL, CSecret &pvchSecretH) const;
+
+ CMalleablePubKey GetMalleablePubKey() const;
+
+ bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant);
+ bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant, CKey &privKeyVariant);
+};
+
+class CMalleableKeyView
+{
+private:
+ CSecret vchSecretL;
+ std::vector<unsigned char> vchPubKeyH;
+
+ // disabled constructor
+ CMalleableKeyView() { };
+
+ static const unsigned char CURRENT_VERSION = 1;
+
+public:
+ CMalleableKeyView(const CMalleableKey &b);
+ CMalleableKeyView(const CSecret &L, const CPubKey &pvchPubKeyH);
+
+ CMalleableKeyView(const CMalleableKeyView &b);
+ CMalleableKeyView& operator=(const CMalleableKey &b);
+ ~CMalleableKeyView();
+
+ CMalleablePubKey GetMalleablePubKey() const;
+
+ bool CheckKeyVariant(const CPubKey &R, const CPubKey &vchPubKeyVariant);
+};
+
#endif
return Value::null;
}
-// ppcoin: make a public-private key pair
+// Make a public-private key pair
Value makekeypair(const Array& params, bool fHelp)
{
- if (fHelp || params.size() > 1)
+ if (fHelp || params.size() > 0)
throw runtime_error(
- "makekeypair [prefix]\n"
- "Make a public/private key pair.\n"
- "[prefix] is optional preferred prefix for the public key.\n");
+ "makekeypair\n"
+ "Make a public/private key pair.\n");
string strPrefix = "";
if (params.size() > 0)
strPrefix = params[0].get_str();
-
+
CKey key;
- key.MakeNewKey(false);
+ key.MakeNewKey(true);
CPrivKey vchPrivKey = key.GetPrivKey();
Object result;
result.push_back(Pair("PrivateKey", HexStr<CPrivKey::iterator>(vchPrivKey.begin(), vchPrivKey.end())));
+
+ bool fCompressed;
+ CSecret vchSecret = key.GetSecret(fCompressed);
+ result.push_back(Pair("Secret", HexStr<CSecret::iterator>(vchSecret.begin(), vchSecret.end())));
result.push_back(Pair("PublicKey", HexStr(key.GetPubKey().Raw())));
return result;
}
+
+Value newmalleablekey(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 0)
+ throw runtime_error(
+ "newmalleablekey\n"
+ "Make a malleable public/private key pair.\n");
+
+ CMalleableKey malleableKey;
+ malleableKey.MakeNewKeys();
+ CMalleablePubKey malleablePubKey = malleableKey.GetMalleablePubKey();
+
+ Object result;
+ result.push_back(Pair("PrivatePair", malleableKey.ToString()));
+ result.push_back(Pair("PublicPair", malleablePubKey.ToString()));
+
+ return result;
+}
+
+Value adjustmalleablekey(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 3)
+ throw runtime_error(
+ "adjustmalleablekey <Malleable key data> <Public key variant data> <R data>\n"
+ "Calculate new private key using provided malleable key, public key and R data.\n");
+
+ CMalleableKey malleableKey;
+ malleableKey.SetString(params[0].get_str());
+
+ CKey privKeyVariant;
+ CPubKey vchPubKeyVariant = CPubKey(ParseHex(params[1].get_str()));
+ CPubKey vchR = CPubKey(ParseHex(params[2].get_str()));
+
+ if (!malleableKey.CheckKeyVariant(vchR,vchPubKeyVariant, privKeyVariant)) {
+ throw runtime_error("Unable to calculate the private key");
+ }
+
+ Object result;
+ bool fCompressed;
+ CSecret vchPrivKeyVariant = privKeyVariant.GetSecret(fCompressed);
+
+ result.push_back(Pair("PrivateKey", CBitcoinSecret(vchPrivKeyVariant, fCompressed).ToString()));
+
+ return result;
+}
+
+Value adjustmalleablepubkey(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() > 2 || params.size() == 0)
+ throw runtime_error(
+ "adjustmalleablepubkey <Malleable public key data>\n"
+ "Calculate new public key using provided malleable public key data.\n");
+
+ CMalleablePubKey malleablePubKey;
+ malleablePubKey.SetString(params[0].get_str());
+
+ CPubKey R, vchPubKeyVariant;
+ malleablePubKey.GetVariant(R, vchPubKeyVariant);
+
+ Object result;
+ result.push_back(Pair("R", HexStr(R.Raw())));
+ result.push_back(Pair("PubkeyVariant", HexStr(vchPubKeyVariant.Raw())));
+ result.push_back(Pair("KeyVariantID", CBitcoinAddress(vchPubKeyVariant.GetID()).ToString()));
+
+ return result;
+}