Exemple #1
0
ec_point bn2point (EC_GROUP const* group, BIGNUM const* number)
{
    EC_POINT* result = EC_POINT_bn2point (group, number, nullptr, nullptr);

    if (result == nullptr)
    {
        throw std::runtime_error ("EC_POINT_bn2point() failed");
    }

    return ec_point::acquire (result);
}
Exemple #2
0
EC_POINT *EC_POINT_hex2point(const EC_GROUP *group,
                             const char *buf, EC_POINT *point, BN_CTX *ctx)
{
    EC_POINT *ret = NULL;
    BIGNUM *tmp_bn = NULL;

    if (!BN_hex2bn(&tmp_bn, buf))
        return NULL;

    ret = EC_POINT_bn2point(group, tmp_bn, point, ctx);

    BN_clear_free(tmp_bn);

    return ret;
}
Exemple #3
0
int StealthSecretSpend(ec_secret& scanSecret, ec_point& ephemPubkey, ec_secret& spendSecret, ec_secret& secretOut)
{
    /*
    
    c  = H(dP)
    R' = R + cG     [without decrypting wallet]
       = (f + c)G   [after decryption of wallet]
         Remember: mod curve.order, pad with 0x00s where necessary?
    */
    
    int rv = 0;
    std::vector<uint8_t> vchOutP;
    
    BN_CTX* bnCtx           = NULL;
    BIGNUM* bnScanSecret    = NULL;
    BIGNUM* bnP             = NULL;
    EC_POINT* P             = NULL;
    BIGNUM* bnOutP          = NULL;
    BIGNUM* bnc             = NULL;
    BIGNUM* bnOrder         = NULL;
    BIGNUM* bnSpend         = NULL;
    
    EC_GROUP* ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1);
    
    if (!ecgrp)
    {
        printf("StealthSecretSpend(): EC_GROUP_new_by_curve_name failed.\n");
        return 1;
    };
    
    if (!(bnCtx = BN_CTX_new()))
    {
        printf("StealthSecretSpend(): BN_CTX_new failed.\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnScanSecret = BN_bin2bn(&scanSecret.e[0], ec_secret_size, BN_new())))
    {
        printf("StealthSecretSpend(): bnScanSecret BN_bin2bn failed.\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnP = BN_bin2bn(&ephemPubkey[0], ephemPubkey.size(), BN_new())))
    {
        printf("StealthSecretSpend(): bnP BN_bin2bn failed\n");
        rv = 1;
        goto End;
    };
    
    if (!(P = EC_POINT_bn2point(ecgrp, bnP, NULL, bnCtx)))
    {
        printf("StealthSecretSpend(): P EC_POINT_bn2point failed\n");
        rv = 1;
        goto End;
    };
    
    // -- dP
    if (!EC_POINT_mul(ecgrp, P, NULL, P, bnScanSecret, bnCtx))
    {
        printf("StealthSecretSpend(): dP EC_POINT_mul failed\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnOutP = EC_POINT_point2bn(ecgrp, P, POINT_CONVERSION_COMPRESSED, BN_new(), bnCtx)))
    {
        printf("StealthSecretSpend(): P EC_POINT_bn2point failed\n");
        rv = 1;
        goto End;
    };
    
    
    vchOutP.resize(ec_compressed_size);
    if (BN_num_bytes(bnOutP) != (int) ec_compressed_size
        || BN_bn2bin(bnOutP, &vchOutP[0]) != (int) ec_compressed_size)
    {
        printf("StealthSecretSpend(): bnOutP incorrect length.\n");
        rv = 1;
        goto End;
    };
    
    uint8_t hash1[32];
    SHA256(&vchOutP[0], vchOutP.size(), (uint8_t*)hash1);
    
    
    if (!(bnc = BN_bin2bn(&hash1[0], 32, BN_new())))
    {
        printf("StealthSecretSpend(): BN_bin2bn failed\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnOrder = BN_new())
        || !EC_GROUP_get_order(ecgrp, bnOrder, bnCtx))
    {
        printf("StealthSecretSpend(): EC_GROUP_get_order failed\n");
        rv = 1;
        goto End;
    };
    
    if (!(bnSpend = BN_bin2bn(&spendSecret.e[0], ec_secret_size, BN_new())))
    {
        printf("StealthSecretSpend(): bnSpend BN_bin2bn failed.\n");
        rv = 1;
        goto End;
    };
    
    //if (!BN_add(r, a, b)) return 0;
    //return BN_nnmod(r, r, m, ctx);
    if (!BN_mod_add(bnSpend, bnSpend, bnc, bnOrder, bnCtx))
    {
        printf("StealthSecretSpend(): bnSpend BN_mod_add failed.\n");
        rv = 1;
        goto End;
    };
    
    if (BN_is_zero(bnSpend)) // possible?
    {
        printf("StealthSecretSpend(): bnSpend is zero.\n");
        rv = 1;
        goto End;
    };
    
    if (BN_num_bytes(bnSpend) != (int) ec_secret_size
        || BN_bn2bin(bnSpend, &secretOut.e[0]) != (int) ec_secret_size)
    {
        printf("StealthSecretSpend(): bnSpend incorrect length.\n");
        rv = 1;
        goto End;
    };
    
    End:
    if (bnSpend)        BN_free(bnSpend);
    if (bnOrder)        BN_free(bnOrder);
    if (bnc)            BN_free(bnc);
    if (bnOutP)         BN_free(bnOutP);
    if (P)              EC_POINT_free(P);
    if (bnP)            BN_free(bnP);
    if (bnScanSecret)   BN_free(bnScanSecret);
    if (bnCtx)          BN_CTX_free(bnCtx);
    EC_GROUP_free(ecgrp);
    
    return rv;
};
Exemple #4
0
int StealthSecret(ec_secret& secret, ec_point& pubkey, const ec_point& pkSpend, ec_secret& sharedSOut, ec_point& pkOut)
{
    /*
    
    send:
        secret = ephem_secret, pubkey = scan_pubkey
    
    receive:
        secret = scan_secret, pubkey = ephem_pubkey
        c = H(dP)
    
    Q = public scan key (EC point, 33 bytes)
    d = private scan key (integer, 32 bytes)
    R = public spend key
    f = private spend key

    Q = dG  //单次使用的私钥
    R = fG
    
    Sender (has Q and R, not d or f):
    
    P = eG

    c = H(eQ) = H(dP)
    R' = R + cG
    
    
    Recipient gets R' and P
    
    test 0 and infinity?
    */
    
    int rv = 0;
    std::vector<uint8_t> vchOutQ;
    
    BN_CTX* bnCtx   = NULL;
    BIGNUM* bnEphem = NULL;
    BIGNUM* bnQ     = NULL;
    EC_POINT* Q     = NULL;
    BIGNUM* bnOutQ  = NULL;
    BIGNUM* bnc     = NULL;
    EC_POINT* C     = NULL;
    BIGNUM* bnR     = NULL;
    EC_POINT* R     = NULL;
    EC_POINT* Rout  = NULL;
    BIGNUM* bnOutR  = NULL;
    
    EC_GROUP* ecgrp = EC_GROUP_new_by_curve_name(NID_secp256k1);
    
    if (!ecgrp)
    {
        printf("StealthSecret(): EC_GROUP_new_by_curve_name failed.\n");
        return 1;
    };
    
    if (!(bnCtx = BN_CTX_new()))
    {
        printf("StealthSecret(): BN_CTX_new failed.\n");
        rv = 2;
        goto End;
    };
    
    if (!(bnEphem = BN_bin2bn(&secret.e[0], ec_secret_size, BN_new())))
    {
        printf("StealthSecret(): bnEphem BN_bin2bn failed.\n");
        rv = 3;
        goto End;
    };
    
    if (!(bnQ = BN_bin2bn(&pubkey[0], pubkey.size(), BN_new())))
    {
        printf("StealthSecret(): bnQ BN_bin2bn failed\n");
        rv = 4;
        goto End;
    };
    
    if (!(Q = EC_POINT_bn2point(ecgrp, bnQ, NULL, bnCtx)))
    {
        printf("StealthSecret(): Q EC_POINT_bn2point failed\n");
        rv = 5;
        goto End;
    };
    
    // -- eQ
    // EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *n, const EC_POINT *q, const BIGNUM *m, BN_CTX *ctx);
    // EC_POINT_mul calculates the value generator * n + q * m and stores the result in r. The value n may be NULL in which case the result is just q * m. 
    if (!EC_POINT_mul(ecgrp, Q, NULL, Q, bnEphem, bnCtx))
    {
        printf("StealthSecret(): eQ EC_POINT_mul failed\n");
        rv = 6;
        goto End;
    };
    
    if (!(bnOutQ = EC_POINT_point2bn(ecgrp, Q, POINT_CONVERSION_COMPRESSED, BN_new(), bnCtx)))
    {
        printf("StealthSecret(): Q EC_POINT_bn2point failed\n");
        rv = 7;
        goto End;
    };
    
    
    vchOutQ.resize(ec_compressed_size);
    if (BN_num_bytes(bnOutQ) != (int) ec_compressed_size
        || BN_bn2bin(bnOutQ, &vchOutQ[0]) != (int) ec_compressed_size)
    {
        printf("StealthSecret(): bnOutQ incorrect length.\n");
        rv = 8;
        goto End;
    };
    
    SHA256(&vchOutQ[0], vchOutQ.size(), &sharedSOut.e[0]);
    
    if (!(bnc = BN_bin2bn(&sharedSOut.e[0], ec_secret_size, BN_new())))
    {
        printf("StealthSecret(): BN_bin2bn failed\n");
        rv = 9;
        goto End;
    };
    
    // -- cG
    if (!(C = EC_POINT_new(ecgrp)))
    {
        printf("StealthSecret(): C EC_POINT_new failed\n");
        rv = 10;
        goto End;
    };
    
    if (!EC_POINT_mul(ecgrp, C, bnc, NULL, NULL, bnCtx))
    {
        printf("StealthSecret(): C EC_POINT_mul failed\n");
        rv = 11;
        goto End;
    };
    
    if (!(bnR = BN_bin2bn(&pkSpend[0], pkSpend.size(), BN_new())))
    {
        printf("StealthSecret(): bnR BN_bin2bn failed\n");
        rv = 12;
        goto End;
    };
    
    
    if (!(R = EC_POINT_bn2point(ecgrp, bnR, NULL, bnCtx)))
    {
        printf("StealthSecret(): R EC_POINT_bn2point failed\n");
        rv = 13;
        goto End;
    };
    
    if (!EC_POINT_mul(ecgrp, C, bnc, NULL, NULL, bnCtx))
    {
        printf("StealthSecret(): C EC_POINT_mul failed\n");
        rv = 14;
        goto End;
    };
    
    if (!(Rout = EC_POINT_new(ecgrp)))
    {
        printf("StealthSecret(): Rout EC_POINT_new failed\n");
        rv = 15;
        goto End;
    };
    
    if (!EC_POINT_add(ecgrp, Rout, R, C, bnCtx))
    {
        printf("StealthSecret(): Rout EC_POINT_add failed\n");
        rv = 16;
        goto End;
    };
    
    if (!(bnOutR = EC_POINT_point2bn(ecgrp, Rout, POINT_CONVERSION_COMPRESSED, BN_new(), bnCtx)))
    {
        printf("StealthSecret(): Rout EC_POINT_bn2point failed\n");
        rv = 17;
        goto End;
    };
    
    
    pkOut.resize(ec_compressed_size);
    if (BN_num_bytes(bnOutR) != (int) ec_compressed_size
        || BN_bn2bin(bnOutR, &pkOut[0]) != (int) ec_compressed_size)
    {
        printf("StealthSecret(): pkOut incorrect length.\n");
        rv = 18;
        goto End;
    };
    
    End:
    if (bnOutR)     BN_free(bnOutR);
    if (Rout)       EC_POINT_free(Rout);
    if (R)          EC_POINT_free(R);
    if (bnR)        BN_free(bnR);
    if (C)          EC_POINT_free(C);
    if (bnc)        BN_free(bnc);
    if (bnOutQ)     BN_free(bnOutQ);
    if (Q)          EC_POINT_free(Q);
    if (bnQ)        BN_free(bnQ);
    if (bnEphem)    BN_free(bnEphem);
    if (bnCtx)      BN_CTX_free(bnCtx);
    EC_GROUP_free(ecgrp);
    
    return rv;
};
Exemple #5
0
int verifyRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, const uint8_t *pPubkeys, const uint8_t *pSigc, const uint8_t *pSigr)
{
    if (fDebugRingSig)
    {
        // LogPrintf("%s size %d\n", __func__, nRingSize); // happens often
    };

    int rv = 0;

    BN_CTX_start(bnCtx);

    BIGNUM   *bnT   = BN_CTX_get(bnCtx);
    BIGNUM   *bnH   = BN_CTX_get(bnCtx);
    BIGNUM   *bnC   = BN_CTX_get(bnCtx);
    BIGNUM   *bnR   = BN_CTX_get(bnCtx);
    BIGNUM   *bnSum = BN_CTX_get(bnCtx);
    EC_POINT *ptT1  = NULL;
    EC_POINT *ptT2  = NULL;
    EC_POINT *ptT3  = NULL;
    EC_POINT *ptPk  = NULL;
    EC_POINT *ptKi  = NULL;
    EC_POINT *ptL   = NULL;
    EC_POINT *ptR   = NULL;
    EC_POINT *ptSi  = NULL;

    uint8_t tempData[66]; // hold raw point data to hash
    uint256 commitHash;
    CHashWriter ssCommitHash(SER_GETHASH, PROTOCOL_VERSION);

    ssCommitHash << txnHash;

    // zero sum
    if (!bnSum || !(BN_zero(bnSum)))
    {
        LogPrintf("%s: BN_zero failed.\n", __func__);
        rv = 1; goto End;
    };

    if (   !(ptT1 = EC_POINT_new(ecGrp))
        || !(ptT2 = EC_POINT_new(ecGrp))
        || !(ptT3 = EC_POINT_new(ecGrp))
        || !(ptPk = EC_POINT_new(ecGrp))
        || !(ptKi = EC_POINT_new(ecGrp))
        || !(ptL  = EC_POINT_new(ecGrp))
        || !(ptSi = EC_POINT_new(ecGrp))
        || !(ptR  = EC_POINT_new(ecGrp)))
    {
        LogPrintf("%s: EC_POINT_new failed.\n", __func__);
        rv = 1; goto End;
    };

    // get keyimage as point
    if (!(bnT = BN_bin2bn(&keyImage[0], EC_COMPRESSED_SIZE, bnT))
        || !(ptKi) || !(ptKi = EC_POINT_bn2point(ecGrp, bnT, ptKi, bnCtx)))
    {
        LogPrintf("%s: extract ptKi failed.\n", __func__);
        rv = 1; goto End;
    };

    for (int i = 0; i < nRingSize; ++i)
    {
        // Li = ci * Pi + ri * G
        // Ri = ci * I + ri * Hp(Pi)

        if (   !bnC || !(bnC = BN_bin2bn(&pSigc[i * EC_SECRET_SIZE], EC_SECRET_SIZE, bnC))
            || !bnR || !(bnR = BN_bin2bn(&pSigr[i * EC_SECRET_SIZE], EC_SECRET_SIZE, bnR)))
        {
            LogPrintf("%s: extract bnC and bnR failed.\n", __func__);
            rv = 1; goto End;
        };

        // get Pk i as point
        if (!(bnT = BN_bin2bn(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT))
            || !(ptPk) || !(ptPk = EC_POINT_bn2point(ecGrp, bnT, ptPk, bnCtx)))
        {
            LogPrintf("%s: extract ptPk failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT1 = ci * Pi
        if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptPk, bnC, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT2 = ri * G
        if (!EC_POINT_mul(ecGrp, ptT2, bnR, NULL, NULL, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptL = ptT1 + ptT2
        if (!EC_POINT_add(ecGrp, ptL, ptT1, ptT2, bnCtx))
        {
            LogPrintf("%s: EC_POINT_add failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT3 = Hp(Pi)
        if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT3) != 0)
        {
            LogPrintf("%s: hashToEC failed.\n", __func__);
            rv = 1; goto End;
        };

        // DEBUGGING: ------- check if we can find the signer...
        // ptSi = Pi * bnT
        if ((!EC_POINT_mul(ecGrp, ptSi, NULL, ptPk, bnT, bnCtx)
           || false)
        && (rv = errorN(1, "%s: EC_POINT_mul failed.1", __func__)))
            goto End;

        if (0 == EC_POINT_cmp(ecGrp, ptSi, ptKi, bnCtx) )
            LogPrintf("signer is index %d\n", i);
        // DEBUGGING: - End - check if we can find the signer...

        // ptT1 = k1 * I
        if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnC, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptT2 = k2 * ptT3
        if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnR, bnCtx))
        {
            LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
            rv = 1; goto End;
        };

        // ptR = ptT1 + ptT2
        if (!EC_POINT_add(ecGrp, ptR, ptT1, ptT2, bnCtx))
        {
            LogPrintf("%s: EC_POINT_add failed.\n", __func__);
            rv = 1; goto End;
        };

        // sum = (sum + ci) % N
        if (!BN_mod_add(bnSum, bnSum, bnC, bnOrder, bnCtx))
        {
            LogPrintf("%s: BN_mod_add failed.\n", __func__);
            rv = 1; goto End;
        };

        // -- add ptL and ptR to hash
        if (   !(EC_POINT_point2oct(ecGrp, ptL, POINT_CONVERSION_COMPRESSED, &tempData[0],  33, bnCtx) == (int) EC_COMPRESSED_SIZE)
            || !(EC_POINT_point2oct(ecGrp, ptR, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE))
        {
            LogPrintf("%s: extract ptL and ptR failed.\n", __func__);
            rv = 1; goto End;
        };

        ssCommitHash.write((const char*)&tempData[0], 66);
    };

    commitHash = ssCommitHash.GetHash();

    if (!(bnH) || !(bnH = BN_bin2bn(commitHash.begin(), EC_SECRET_SIZE, bnH)))
    {
        LogPrintf("%s: commitHash -> bnH failed.\n", __func__);
        rv = 1; goto End;
    };

    if (!BN_mod(bnH, bnH, bnOrder, bnCtx))
    {
        LogPrintf("%s: BN_mod failed.\n", __func__);
        rv = 1; goto End;
    };

    // bnT = (bnH - bnSum) % N
    if (!BN_mod_sub(bnT, bnH, bnSum, bnOrder, bnCtx))
    {
        LogPrintf("%s: BN_mod_sub failed.\n", __func__);
        rv = 1; goto End;
    };

    // test bnT == 0  (bnSum == bnH)
    if (!BN_is_zero(bnT))
    {
        LogPrintf("%s: signature does not verify.\n", __func__);
        rv = 2;
    };

    End:

    EC_POINT_free(ptT1);
    EC_POINT_free(ptT2);
    EC_POINT_free(ptT3);
    EC_POINT_free(ptPk);
    EC_POINT_free(ptKi);
    EC_POINT_free(ptL);
    EC_POINT_free(ptR);
    EC_POINT_free(ptSi);

    BN_CTX_end(bnCtx);

    return rv;
};
Exemple #6
0
int generateRingSignature(data_chunk &keyImage, uint256 &txnHash, int nRingSize, int nSecretOffset, ec_secret secret, const uint8_t *pPubkeys, uint8_t *pSigc, uint8_t *pSigr)
{
    if (fDebugRingSig)
        LogPrintf("%s: Ring size %d.\n", __func__, nRingSize);

    int rv = 0;
    int nBytes;

    BN_CTX_start(bnCtx);

    BIGNUM   *bnKS  = BN_CTX_get(bnCtx);
    BIGNUM   *bnK1  = BN_CTX_get(bnCtx);
    BIGNUM   *bnK2  = BN_CTX_get(bnCtx);
    BIGNUM   *bnT   = BN_CTX_get(bnCtx);
    BIGNUM   *bnH   = BN_CTX_get(bnCtx);
    BIGNUM   *bnSum = BN_CTX_get(bnCtx);
    EC_POINT *ptT1  = NULL;
    EC_POINT *ptT2  = NULL;
    EC_POINT *ptT3  = NULL;
    EC_POINT *ptPk  = NULL;
    EC_POINT *ptKi  = NULL;
    EC_POINT *ptL   = NULL;
    EC_POINT *ptR   = NULL;

    uint8_t tempData[66]; // hold raw point data to hash
    uint256 commitHash;
    ec_secret scData1, scData2;

    CHashWriter ssCommitHash(SER_GETHASH, PROTOCOL_VERSION);

    ssCommitHash << txnHash;

    // zero signature
    memset(pSigc, 0, EC_SECRET_SIZE * nRingSize);
    memset(pSigr, 0, EC_SECRET_SIZE * nRingSize);


    // ks = random 256 bit int mod P
    if (GenerateRandomSecret(scData1)
    && (rv = errorN(1, "%s: GenerateRandomSecret failed.", __func__)))
        goto End;

    if (!bnKS || !(BN_bin2bn(&scData1.e[0], EC_SECRET_SIZE, bnKS)))
    {
        LogPrintf("%s: BN_bin2bn failed.\n", __func__);
        rv = 1; goto End;
    };

    // zero sum
    if (!bnSum || !(BN_zero(bnSum)))
    {
        LogPrintf("%s: BN_zero failed.\n", __func__);
        rv = 1; goto End;
    };

    if (   !(ptT1 = EC_POINT_new(ecGrp))
        || !(ptT2 = EC_POINT_new(ecGrp))
        || !(ptT3 = EC_POINT_new(ecGrp))
        || !(ptPk = EC_POINT_new(ecGrp))
        || !(ptKi = EC_POINT_new(ecGrp))
        || !(ptL  = EC_POINT_new(ecGrp))
        || !(ptR  = EC_POINT_new(ecGrp)))
    {
        LogPrintf("%s: EC_POINT_new failed.\n", __func__);
        rv = 1; goto End;
    };

    // get keyimage as point
    if (!(bnT = BN_bin2bn(&keyImage[0], EC_COMPRESSED_SIZE, bnT))
        || !(ptKi) || !(ptKi = EC_POINT_bn2point(ecGrp, bnT, ptKi, bnCtx)))
    {
        LogPrintf("%s: extract ptKi failed.\n", __func__);
        rv = 1; goto End;
    };

    for (int i = 0; i < nRingSize; ++i)
    {
        if (i == nSecretOffset)
        {
            // k = random 256 bit int mod P
            // L = k * G
            // R = k * HashToEC(PKi)

            if (!EC_POINT_mul(ecGrp, ptL, bnKS, NULL, NULL, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT1) != 0)
            {
                LogPrintf("%s: hashToEC failed.\n", __func__);
                rv = 1; goto End;
            };

            if (!EC_POINT_mul(ecGrp, ptR, NULL, ptT1, bnKS, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

        } else
        {
            // k1 = random 256 bit int mod P
            // k2 = random 256 bit int mod P
            // Li = k1 * Pi + k2 * G
            // Ri = k1 * I + k2 * Hp(Pi)
            // ci = k1
            // ri = k2

            if (GenerateRandomSecret(scData1) != 0
                || !bnK1 || !(BN_bin2bn(&scData1.e[0], EC_SECRET_SIZE, bnK1))
                || GenerateRandomSecret(scData2) != 0
                || !bnK2 || !(BN_bin2bn(&scData2.e[0], EC_SECRET_SIZE, bnK2)))
            {
                LogPrintf("%s: k1 and k2 failed.\n", __func__);
                rv = 1; goto End;
            };

            // get Pk i as point
            if (!(bnT = BN_bin2bn(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT))
                || !(ptPk) || !(ptPk = EC_POINT_bn2point(ecGrp, bnT, ptPk, bnCtx)))
            {
                LogPrintf("%s: extract ptPk failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT1 = k1 * Pi
            if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptPk, bnK1, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT2 = k2 * G
            if (!EC_POINT_mul(ecGrp, ptT2, bnK2, NULL, NULL, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptL = ptT1 + ptT2
            if (!EC_POINT_add(ecGrp, ptL, ptT1, ptT2, bnCtx))
            {
                LogPrintf("%s: EC_POINT_add failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT3 = Hp(Pi)
            if (hashToEC(&pPubkeys[i * EC_COMPRESSED_SIZE], EC_COMPRESSED_SIZE, bnT, ptT3) != 0)
            {
                LogPrintf("%s: hashToEC failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT1 = k1 * I
            if (!EC_POINT_mul(ecGrp, ptT1, NULL, ptKi, bnK1, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptT2 = k2 * ptT3
            if (!EC_POINT_mul(ecGrp, ptT2, NULL, ptT3, bnK2, bnCtx))
            {
                LogPrintf("%s: EC_POINT_mul failed.\n", __func__);
                rv = 1; goto End;
            };

            // ptR = ptT1 + ptT2
            if (!EC_POINT_add(ecGrp, ptR, ptT1, ptT2, bnCtx))
            {
                LogPrintf("%s: EC_POINT_add failed.\n", __func__);
                rv = 1; goto End;
            };

            memcpy(&pSigc[i * EC_SECRET_SIZE], &scData1.e[0], EC_SECRET_SIZE);
            memcpy(&pSigr[i * EC_SECRET_SIZE], &scData2.e[0], EC_SECRET_SIZE);

            // sum = (sum + sigc) % N , sigc == bnK1
            if (!BN_mod_add(bnSum, bnSum, bnK1, bnOrder, bnCtx))
            {
                LogPrintf("%s: BN_mod_add failed.\n", __func__);
                rv = 1; goto End;
            };
        };

        // -- add ptL and ptR to hash
        if (   !(EC_POINT_point2oct(ecGrp, ptL, POINT_CONVERSION_COMPRESSED, &tempData[0],  33, bnCtx) == (int) EC_COMPRESSED_SIZE)
            || !(EC_POINT_point2oct(ecGrp, ptR, POINT_CONVERSION_COMPRESSED, &tempData[33], 33, bnCtx) == (int) EC_COMPRESSED_SIZE))
        {
            LogPrintf("%s: extract ptL and ptR failed.\n", __func__);
            rv = 1; goto End;
        };

        ssCommitHash.write((const char*)&tempData[0], 66);
    };

    commitHash = ssCommitHash.GetHash();

    if (!(bnH) || !(bnH = BN_bin2bn(commitHash.begin(), EC_SECRET_SIZE, bnH)))
    {
        LogPrintf("%s: commitHash -> bnH failed.\n", __func__);
        rv = 1; goto End;
    };


    if (!BN_mod(bnH, bnH, bnOrder, bnCtx)) // this is necessary
    {
        LogPrintf("%s: BN_mod failed.\n", __func__);
        rv = 1; goto End;
    };

    // sigc[nSecretOffset] = (bnH - bnSum) % N
    if (!BN_mod_sub(bnT, bnH, bnSum, bnOrder, bnCtx))
    {
        LogPrintf("%s: BN_mod_sub failed.\n", __func__);
        rv = 1; goto End;
    };

    if ((nBytes = BN_num_bytes(bnT)) > (int)EC_SECRET_SIZE
        || BN_bn2bin(bnT, &pSigc[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes)
    {
        LogPrintf("%s: bnT -> pSigc failed.\n", __func__);
        rv = 1; goto End;
    };

    // sigr[nSecretOffset] = (bnKS - sigc[nSecretOffset] * bnSecret) % N
    // reuse bnH for bnSecret
    if (!bnH || !(BN_bin2bn(&secret.e[0], EC_SECRET_SIZE, bnH)))
    {
        LogPrintf("%s: BN_bin2bn failed.\n", __func__);
        rv = 1; goto End;
    };

    // bnT = sigc[nSecretOffset] * bnSecret , TODO: mod N ?
    if (!BN_mul(bnT, bnT, bnH, bnCtx))
    {
        LogPrintf("%s: BN_mul failed.\n", __func__);
        rv = 1; goto End;
    };

    if (!BN_mod_sub(bnT, bnKS, bnT, bnOrder, bnCtx))
    {
        LogPrintf("%s: BN_mod_sub failed.\n", __func__);
        rv = 1; goto End;
    };

    if ((nBytes = BN_num_bytes(bnT)) > (int) EC_SECRET_SIZE
        || BN_bn2bin(bnT, &pSigr[nSecretOffset * EC_SECRET_SIZE + (EC_SECRET_SIZE-nBytes)]) != nBytes)
    {
        LogPrintf("%s: bnT -> pSigr failed.\n", __func__);
        rv = 1; goto End;
    };

    End:
    EC_POINT_free(ptT1);
    EC_POINT_free(ptT2);
    EC_POINT_free(ptT3);
    EC_POINT_free(ptPk);
    EC_POINT_free(ptKi);
    EC_POINT_free(ptL);
    EC_POINT_free(ptR);

    BN_CTX_end(bnCtx);

    return rv;
};
Exemple #7
0
int initialiseRingSigs()
{
    if (fDebugRingSig)
        LogPrintf("initialiseRingSigs()\n");

    if (!(ecGrp = EC_GROUP_new_by_curve_name(NID_secp256k1)))
        return errorN(1, "initialiseRingSigs(): EC_GROUP_new_by_curve_name failed.");

    if (!(bnCtx = BN_CTX_new()))
        return errorN(1, "initialiseRingSigs(): BN_CTX_new failed.");

    BN_CTX_start(bnCtx);

    //Create a new EC group for the keyImage with all of the characteristics of ecGrp.
    if(!(ecGrpKi = EC_GROUP_dup(ecGrp))){
	return errorN(1, "initialiseRingSigs(): EC_GROUP_dup failed.");
    }

    // get order and cofactor
    bnOrder = BN_new();
    if(!EC_GROUP_get_order(ecGrp, bnOrder, bnCtx)){
        return errorN(1, "initialiseRingSigs(): EC_GROUP_get_order failed.");
    }

    BIGNUM *bnCofactor = BN_CTX_get(bnCtx);
    if(!EC_GROUP_get_cofactor(ecGrp, bnCofactor, bnCtx)){
    	return errorN(1, "initialiseRingSigs(): EC_GROUP_get_cofactor failed.");
    }

    // get the original generator
    EC_POINT *ptBase = const_cast<EC_POINT*>(EC_GROUP_get0_generator(ecGrp)); //PS: never clear this point

    // create key image basepoint variable
    EC_POINT *ptBaseKi = EC_POINT_new(ecGrpKi);
    BIGNUM *bnBaseKi = BN_CTX_get(bnCtx);

    // get original basepoint in BIG NUMS.
    EC_POINT_point2bn(ecGrp, ptBase, POINT_CONVERSION_COMPRESSED, bnBaseKi, bnCtx);

    //create "1" in BIG NUMS
    BIGNUM *bnBaseKiAdd = BN_CTX_get(bnCtx);
    std::string num_str = "1";
    BN_dec2bn(&bnBaseKiAdd, num_str.c_str());

    // add 1 to original base point and store in key image basepoint (BIG NUMS)
    BN_add(bnBaseKi, bnBaseKi, bnBaseKiAdd);

    // key image basepoint from bignum to point in ptBaseKi
    if(!EC_POINT_bn2point(ecGrp, bnBaseKi, ptBaseKi, bnCtx))
       return errorN(1, "initialiseRingSigs(): EC_POINT_bn2point failed.");

    // set generator of ecGrpKi
    if(!EC_GROUP_set_generator(ecGrpKi, ptBaseKi, bnOrder, bnCofactor)){
	 return errorN(1, "initialiseRingSigs(): EC_GROUP_set_generator failed.");
    }

    if (fDebugRingSig)
    {
        // Debugging...
        const EC_POINT *generator = EC_GROUP_get0_generator(ecGrp);
        const EC_POINT *generatorKi = EC_GROUP_get0_generator(ecGrpKi);
        char *genPoint = EC_POINT_point2hex(ecGrp, generator, POINT_CONVERSION_UNCOMPRESSED, bnCtx);
        char *genPointKi = EC_POINT_point2hex(ecGrpKi, generatorKi, POINT_CONVERSION_UNCOMPRESSED, bnCtx);

        LogPrintf("generator ecGrp:   %s\ngenerator ecGrpKi: %s\n", genPoint, genPointKi);
    }

    EC_POINT_free(ptBaseKi);
    BN_CTX_end(bnCtx);
    return 0;
};