예제 #1
0
/**
 * \brief Signs a message using a specific Ed25519 private key.
 *
 * \param signature The signature value.
 * \param privateKey The private key to use to sign the message.
 * \param publicKey The public key corresponding to \a privateKey.
 * \param message Points to the message to be signed.
 * \param len The length of the \a message to be signed.
 *
 * \sa verify(), derivePublicKey()
 */
void Ed25519::sign(uint8_t signature[64], const uint8_t privateKey[32],
                   const uint8_t publicKey[32], const void *message, size_t len)
{
    SHA512 hash;
    uint8_t *buf = (uint8_t *)(hash.state.w); // Reuse hash buffer to save memory.
    limb_t a[NUM_LIMBS_256BIT];
    limb_t r[NUM_LIMBS_256BIT];
    limb_t k[NUM_LIMBS_256BIT];
    limb_t t[NUM_LIMBS_512BIT + 1];
    Point rB;

    // Derive the secret scalar a and the message prefix from the private key.
    deriveKeys(&hash, a, privateKey);

    // Hash the prefix and the message to derive r.
    hash.reset();
    hash.update(buf + 32, 32);
    hash.update(message, len);
    hash.finalize(buf, 0);
    reduceQFromBuffer(r, buf, t);

    // Encode rB into the first half of the signature buffer as R.
    mul(rB, r);
    encodePoint(signature, rB);

    // Hash R, A, and the message to get k.
    hash.reset();
    hash.update(signature, 32); // R
    hash.update(publicKey, 32); // A
    hash.update(message, len);
    hash.finalize(buf, 0);
    reduceQFromBuffer(k, buf, t);

    // Compute s = (r + k * a) mod q.
    Curve25519::mulNoReduce(t, k, a);
    t[NUM_LIMBS_512BIT] = 0;
    reduceQ(t, t);
    BigNumberUtil::add(t, t, r, NUM_LIMBS_256BIT);
    BigNumberUtil::reduceQuick_P(t, t, numQ, NUM_LIMBS_256BIT);
    BigNumberUtil::packLE(signature + 32, 32, t, NUM_LIMBS_256BIT);

    // Clean up.
    clean(a);
    clean(r);
    clean(k);
    clean(t);
    clean(rB);
}
예제 #2
0
/**
 * \brief Verifies a signature using a specific Ed25519 public key.
 *
 * \param signature The signature value to be verified.
 * \param publicKey The public key to use to verify the signature.
 * \param message The message whose signature is to be verified.
 * \param len The length of the \a message to be verified.
 *
 * \return Returns true if the \a signature is valid for \a message;
 * or false if the \a signature is not valid.
 *
 * \sa sign()
 */
bool Ed25519::verify(const uint8_t signature[64], const uint8_t publicKey[32],
                     const void *message, size_t len)
{
    SHA512 hash;
    Point A;
    Point R;
    Point sB;
    Point kA;
    uint8_t *k = (uint8_t *)(hash.state.w); // Reuse hash buffer to save memory.
    bool result = false;

    // Decode the public key and the R component of the signature.
    if (decodePoint(A, publicKey) && decodePoint(R, signature)) {
        // Reconstruct the k value from the signing step.
        hash.reset();
        hash.update(signature, 32);
        hash.update(publicKey, 32);
        hash.update(message, len);
        hash.finalize(k, 0);

        // Calculate s * B.  The s value is stored temporarily in kA.t.
        BigNumberUtil::unpackLE(kA.t, NUM_LIMBS_256BIT, signature + 32, 32);
        mul(sB, kA.t, false);

        // Calculate R + k * A.  We don't need sB.t in equal() below,
        // so we reuse that as a temporary buffer when reducing k.
        reduceQFromBuffer(sB.t, k, kA.x);
        mul(kA, sB.t, A, false);
        add(R, kA);

        // Compare s * B and R + k * A for equality.
        result = equal(sB, R);
    }

    // Clean up and exit.
    clean(A);
    clean(R);
    clean(sB);
    clean(kA);
    return result;
}