Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/lib/freebl/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 12 kB image not shown  

Quelle  rsa_blind.c   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


/*
 * Implementation of RSA Blind Signatures.
 * (https://datatracker.ietf.org/doc/draft-irtf-cfrg-rsa-blind-signatures/)
 */

#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif

#include "secerr.h"
#include "blapi.h"
#include "mpi.h"
#include "secitem.h"
#include "prerr.h"
#include "blapii.h"
#include "secmpi.h"
#include "mpi-priv.h"
#include "pqg.h"

/*#define RSA_DEBUG*/

#define MP_DIGIT_BYTE (MP_DIGIT_BIT / PR_BITS_PER_BYTE)

#ifdef RSA_DEBUG

void
rsaBlind_Print(PRUint8* m, size_t t)
{
    for (int i = 0; i < t; i++) {
        if (i % 16 == 0)
            printf("\n");
        printf("%02x ", m[i]);
    }
    printf("\n \n");
}

void
mp_print_buf(mp_int* mp)
{
    for (int i = MP_USED(mp) - 1; i >= 0; i--) {
        if (i % 2 == 1)
            printf("\n");
        printf("%016lx ", (long unsigned int)MP_DIGIT(mp, i));
    }
    printf("\n \n");
}
#endif

/*
 * 4.1. Prepare
 * There are two types of preparation functions:
 * an identity preparation function, and a randomized preparation function.
 * The identity preparation function returns the input message without transformation,
 * i.e., msg = PrepareIdentity(msg).
 * The randomized preparation function augments the input message with fresh randomness.
 *
 * Inputs:
 * - msg, message to be signed, a byte string
 *
 * Outputs:
 * - input_msg, a byte string that is 32 bytes longer than msg

 * Steps:
 *  1. msgPrefix = random(32)
 *  2. input_msg = concat(msgPrefix, msg)
 *  3. output input_msg
 */


SECStatus
RSABlinding_Prepare(PRUint8* preparedMessage, size_t preparedMessageLen, const PRUint8* msg,
                    size_t msgLen, PRBool isDeterministic)
{
    if (!preparedMessage || !msg) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    /* The identity preparation function: */
    if (isDeterministic) {
        if (preparedMessageLen < msgLen) {
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            return SECFailure;
        }
        PORT_Memcpy(preparedMessage, msg, msgLen);
    }
    /* The randomized preparation function: */
    else {
        /* 1. msgPrefix = random(32)*/
        PRUint8 lenRandom = 32;
        if (msgLen > UINT32_MAX - lenRandom) {
            PORT_SetError(SEC_ERROR_INPUT_LEN);
            return SECFailure;
        }
        if (preparedMessageLen < msgLen + lenRandom) {
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
            return SECFailure;
        }

        RNG_GenerateGlobalRandomBytes(preparedMessage, lenRandom);
        /* 2. input_msg = concat(msgPrefix, msg)*/
        PORT_Memcpy(preparedMessage + lenRandom, msg, msgLen);
    }

    return SECSuccess;
}

/* RSA Blind Signatures
 * Blind(pkS, msg)
 * Parameters:
 * - kLen, the length in bytes of the RSA modulus n
 * - Hash, the hash function used to hash the message
 * - MGF, the mask generation function
 * - sLen, the length in bytes of the salt
 *
 * Inputs:
 * - pkS, server public key (n, e)
 * - msg, message to be signed, a byte string
 *
 * Outputs:
 * - blinded_msg, a byte string of length kLen
 * - inv, an integer used to unblind the signature in Finalize
 */


/* The length of the random buffer is n. */
SECStatus
RSABlinding_Blind(HASH_HashType hashAlg, PRUint8* blindedMsg, size_t blindedMsgLen,
                  PRUint8* inv, size_t invLen, const PRUint8* msg, size_t msgLen,
                  const PRUint8* salt, size_t saltLen,
                  RSAPublicKey* pkS, const PRUint8* randomBuf, size_t randomBufLen)
{
    if (!blindedMsgLen || !inv || !msg || !pkS) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    mp_err err = MP_OKAY;
    const size_t modulus_len = pkS->modulus.len;

    if (blindedMsgLen != modulus_len || invLen != modulus_len) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (randomBufLen != 0 && randomBufLen != modulus_len) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if ((PRUint64)pkS->modulus.len * PR_BITS_PER_BYTE - 1 > UINT32_MAX) {
        PORT_SetError(SEC_ERROR_INPUT_LEN);
        return SECFailure;
    }

    PRUint8* encoded_msg = PORT_ZAlloc(modulus_len);
    PRUint8* rBuf = PORT_ZAlloc(modulus_len);
    PRUint8* xBuf = PORT_ZAlloc(modulus_len);

    mp_int m, n, r, mask, invR, rsavp1, blindSign;
    MP_DIGITS(&m) = 0;
    MP_DIGITS(&invR) = 0;
    MP_DIGITS(&rsavp1) = 0;
    MP_DIGITS(&blindSign) = 0;
    MP_DIGITS(&n) = 0;
    MP_DIGITS(&r) = 0;
    MP_DIGITS(&mask) = 0;

    CHECK_MPI_OK(mp_init(&m));
    CHECK_MPI_OK(mp_init(&invR));
    CHECK_MPI_OK(mp_init(&rsavp1));
    CHECK_MPI_OK(mp_init(&blindSign));
    CHECK_MPI_OK(mp_init(&r));
    CHECK_MPI_OK(mp_init(&n));
    CHECK_MPI_OK(mp_init(&mask));

    CHECK_MPI_OK(mp_read_unsigned_octets(&n, pkS->modulus.data, pkS->modulus.len));
    SECStatus rv = SECFailure;
    size_t bit_len_n = pkS->modulus.len * PR_BITS_PER_BYTE - 1;

    if (!randomBuf || randomBufLen == 0) {
        CHECK_MPI_OK(mp_2expt(&mask, bit_len_n + 1));
        CHECK_MPI_OK(mp_sub_d(&mask, 1, &mask));
        do {
            CHECK_MPI_OK(mpp_random_secure(&r));
            for (size_t i = 0; i < mask.alloc; i++) {
                r.dp[i] = mask.dp[i] & r.dp[i];
            }
        } while (mp_cmp(&r, &n) != MP_LT);
        CHECK_MPI_OK(mp_init_copy(&r, &mask));
    } else {
        CHECK_MPI_OK(mp_read_unsigned_octets(&r, randomBuf, pkS->modulus.len));
    }

    /* 1. encoded_msg = EMSA-PSS-ENCODE(msg, bit_len(n)). */
    PRUint8 msgHash[HASH_LENGTH_MAX] = { 0 };
    rv = PQG_HashBuf(hashAlg, msgHash, msg, msgLen);
    if (rv != SECSuccess) {
        goto cleanup;
    }

    rv = RSA_EMSAEncodePSS(encoded_msg, pkS->modulus.len, bit_len_n, msgHash, hashAlg, hashAlg, salt, saltLen);

    /* 2. If EMSA-PSS-ENCODE raises an error, raise the error and stop. */
    if (rv != SECSuccess) {
        PORT_SetError(SEC_ERROR_FAILED_TO_ENCODE_DATA);
        goto cleanup;
    }

#ifdef RSA_DEBUG
    printf("encoded_msg: \n");
    rsaBlind_Print(encoded_msg, modulus_len);
#endif

    /* 3. m = bytes_to_int(encoded_msg). */
    CHECK_MPI_OK(mp_read_unsigned_octets(&m, encoded_msg, pkS->modulus.len));

    /* 4. c = mp_is_coprime(m, n).
     ** 5. If c is false, raise an "invalid input" error and stop.
     ** 7. inv = inverse_mod(r, n)
     */

    err = mp_invmod(&r, &n, &invR);
    if (err == MP_UNDEF) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        goto cleanup;
    } else if (err) {
        goto cleanup;
    }

#ifdef RSA_DEBUG
    printf("inverse r: \n");
    mp_print_buf(&invR);
#endif

    /* 9. x = RSAVP1(pkS, r)*/
    CHECK_MPI_OK(mp_to_fixlen_octets(&r, rBuf, pkS->modulus.len));
    rv = RSA_PublicKeyOp(pkS, xBuf, rBuf);
    if (rv != SECSuccess) {
        goto cleanup;
    }
    CHECK_MPI_OK(mp_read_unsigned_octets(&rsavp1, xBuf, pkS->modulus.len));

#ifdef RSA_DEBUG
    printf("x (RSAVP1): \n");
    mp_print_buf(&rsavp1);
#endif

    /* 10. z = m * x mod n*/
    CHECK_MPI_OK(mp_mulmod(&m, &rsavp1, &n, &blindSign));

#ifdef RSA_DEBUG
    printf("blindSign: \n");
    mp_print_buf(&blindSign);
#endif

    CHECK_MPI_OK(mp_to_fixlen_octets(&blindSign, blindedMsg, blindedMsgLen));
    CHECK_MPI_OK(mp_to_fixlen_octets(&invR, inv, invLen));

cleanup:
    mp_clear(&m);
    mp_clear(&n);
    mp_clear(&r);
    mp_clear(&invR);
    mp_clear(&rsavp1);
    mp_clear(&blindSign);
    mp_clear(&mask);

    PORT_Free(encoded_msg);
    PORT_Free(rBuf);
    PORT_Free(xBuf);

    if (err) {
        MP_TO_SEC_ERROR(err);
        return SECFailure;
    }

    return rv;
}

/* 4.3. BlindSign
 * BlindSign(skS, blinded_msg)
 *
 * Parameters:
 *  - kLen, the length in bytes of the RSA modulus n
 *
 * Inputs:
 *  - skS, server private key
 *  - blinded_msg, encoded and blinded message to be signed, a byte string
 */


SECStatus
RSABlinding_BlindSign(PRUint8* blindSig, size_t blindSigLen,
                      const PRUint8* blindedMsg, size_t blindedMsgLen, RSAPrivateKey* skS, RSAPublicKey* pkS)
{
    SECStatus rv = SECSuccess;
    if (!blindSig || !blindedMsg || !skS) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if ((blindSigLen != skS->modulus.len) || (skS->modulus.len != pkS->modulus.len) || (blindedMsgLen != skS->modulus.len)) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    PRUint8* sBuf = (PRUint8*)PORT_Alloc(skS->modulus.len);
    PRUint8* mPrimeBuf = (PRUint8*)PORT_Alloc(pkS->modulus.len);

    mp_err err = MP_OKAY;
    mp_int z, mPrime;
    MP_DIGITS(&z) = 0;
    MP_DIGITS(&mPrime) = 0;

    CHECK_MPI_OK(mp_init(&z));
    CHECK_MPI_OK(mp_init(&mPrime));

    CHECK_MPI_OK(mp_read_unsigned_octets(&z, blindedMsg, skS->modulus.len));

    /* 2. s = rsasp1(skS, z). */
    rv = RSA_PrivateKeyOp(skS, sBuf, blindedMsg);
    if (rv != SECSuccess) {
        goto cleanup;
    }

#ifdef RSA_DEBUG
    printf("Blinded Signature: \n");
    mp_print_buf(&s);
#endif

    /* 3. mPrime = rsavp1(pkS, s). */
    rv = RSA_PublicKeyOp(pkS, mPrimeBuf, sBuf);
    if (rv != SECSuccess) {
        goto cleanup;
    }

    CHECK_MPI_OK(mp_read_unsigned_octets(&mPrime, mPrimeBuf, skS->modulus.len));

#ifdef RSA_DEBUG
    printf("mPrime: \n");
    mp_print_buf(&mPrime);
#endif

    /* 4. If m != m', raise "signing failure" and stop. */
    PRBool isBlindedMsgCorrect = mp_cmp(&mPrime, &z) == 0;

    /* 5. blind_sig = int_to_bytes(s, kLen). */
    if (isBlindedMsgCorrect) {
        PORT_Memcpy(blindSig, sBuf, skS->modulus.len);
    }

cleanup:
    mp_clear(&z);
    mp_clear(&mPrime);

    PORT_Free(sBuf);
    PORT_Free(mPrimeBuf);

    if (err) {
        MP_TO_SEC_ERROR(err);
        return SECFailure;
    }
    if (rv != SECSuccess) {
        return SECFailure;
    }

    return SECSuccess;
}

/*
 * 4.4. Finalize.
 * Finalize validates the server's response, unblinds the message to produce a signature,
 * verifies it for correctness, and outputs the signature upon success.
 *
 *  Parameters:
 * - kLen, the length in bytes of the RSA modulus n
 * - Hash, the hash function used to hash the message
 * - MGF, the mask generation function
 * - sLen, the length in bytes of the salt
 *
 * Inputs:
 * - pkS, server public key (n, e)
 * - msg, message to be signed, a byte string
 * - blind_sig, signed and blinded element, a byte string of
 *   length kLen
 * - inv, inverse of the blind, an integer
 *
 * Outputs:
 * - sig, a byte string of length kLen
 *
 * Blinded Signature Len should be the same as modulus len.
 */


SECStatus
RSABlinding_Finalize(HASH_HashType hashAlg, PRUint8* signature, const PRUint8* msg, PRUint32 msgLen,
                     const PRUint8* blindSig, size_t blindSigLen,
                     const PRUint8* inv, size_t invLen, RSAPublicKey* pkS, size_t saltLen)
{
    if (!signature || !msg || !blindSig || !inv || !pkS || msgLen == 0) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    if (blindSigLen != pkS->modulus.len || invLen != pkS->modulus.len) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    mp_err err = MP_OKAY;
    SECStatus rv = SECFailure;

    mp_int inv_mp, blindSig_mp, n_mp, sig_mp;
    MP_DIGITS(&inv_mp) = 0;
    MP_DIGITS(&blindSig_mp) = 0;
    MP_DIGITS(&n_mp) = 0;
    MP_DIGITS(&sig_mp) = 0;

    CHECK_MPI_OK(mp_init(&n_mp));
    CHECK_MPI_OK(mp_init(&inv_mp));
    CHECK_MPI_OK(mp_init(&blindSig_mp));
    CHECK_MPI_OK(mp_init(&sig_mp));

    CHECK_MPI_OK(mp_read_unsigned_octets(&n_mp, pkS->modulus.data, pkS->modulus.len));
    CHECK_MPI_OK(mp_read_unsigned_octets(&blindSig_mp, blindSig, pkS->modulus.len));
    CHECK_MPI_OK(mp_read_unsigned_octets(&inv_mp, inv, pkS->modulus.len));

    /* 3. s = z * inv mod n. */
    CHECK_MPI_OK(mp_mulmod(&blindSig_mp, &inv_mp, &n_mp, &sig_mp));

#ifdef RSA_DEBUG
    printf("Computed Signature : \n");
    mp_print_buf(&sig_mp);
#endif

    CHECK_MPI_OK(mp_to_fixlen_octets(&sig_mp, signature, pkS->modulus.len));

    PRUint8 mHash[HASH_LENGTH_MAX] = { 0 };
    rv = PQG_HashBuf(hashAlg, mHash, msg, msgLen);
    if (rv != SECSuccess) {
        PORT_SetError(SEC_ERROR_BAD_DATA);
        goto cleanup;
    }

    /* 5. result = RSASSA-PSS-VERIFY(pkS, msg, sig) with Hash, MGF, and sLen as defined in the parameters. */
    rv = RSA_CheckSignPSS(pkS, hashAlg, hashAlg, saltLen, signature, sig_mp.used * MP_DIGIT_BYTE, mHash, 0);

    /* If result = "valid signature", output sig, else raise "invalid signature" and stop. */
    if (rv != SECSuccess) {
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
    }

#ifdef RSA_DEBUG
    if (rv == SECFailure) {
        printf("%s\n""RSA CheckSignPSS has failed. ");
    } else {
        printf("%s\n""RSA CheckSignPSS has succeeded. ");
    }
#endif

cleanup:
    mp_clear(&inv_mp);
    mp_clear(&blindSig_mp);
    mp_clear(&n_mp);
    mp_clear(&sig_mp);
    if (err) {
        MP_TO_SEC_ERROR(err);
        return SECFailure;
    }

    return rv;
}

Messung V0.5
C=95 H=70 G=83

¤ Dauer der Verarbeitung: 0.6 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.