Skip to content

Potential ECC signing optimization: optional blinding in ecc_sign_hash_internal #798

Description

@headscott

Description

While reviewing ecc_sign_hash_internal, I noticed that the calculation of s = (e + xr) / k performs several additional modular multiplications because a random blinding value b is applied to k.

The current implementation contains:

         /* find s = (e + xr)/k */
         if ((err = ltc_mp_mulmod(pubkey.k, b, p, pubkey.k)) != CRYPT_OK)      { goto error; } /* k = kb */
         if ((err = ltc_mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK)         { goto error; } /* k = 1/kb */
         if ((err = ltc_mp_mulmod(key->k, r, p, s)) != CRYPT_OK)               { goto error; } /* s = xr */
         if ((err = ltc_mp_mulmod(pubkey.k, s, p, s)) != CRYPT_OK)             { goto error; } /* s = xr/kb */
         if ((err = ltc_mp_mulmod(pubkey.k, e, p, e)) != CRYPT_OK)             { goto error; } /* e = e/kb */
         if ((err = ltc_mp_add(e, s, s)) != CRYPT_OK)                          { goto error; } /* s = e/kb + xr/kb */
         if ((err = ltc_mp_mulmod(s, b, p, s)) != CRYPT_OK)                    { goto error; } /* s = b(e/kb + xr/kb) = (e + xr)/k */

Algebraically, the blinding factor cancels out:

kb = k * b

1 / kb = 1 / (k * b)

b * ((e / kb) + (xr / kb))
    = b * ((e + xr) / (k * b))
    = (e + xr) / k

Without blinding, the calculation could therefore be reduced to:

         /* find s = (e + xr)/k */
         if ((err = ltc_mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/k */
         if ((err = ltc_mp_mulmod(key->k, r, p, s)) != CRYPT_OK)       { goto error; }
         if ((err = ltc_mp_add(e, s, s)) != CRYPT_OK)                  { goto error; } /* s = e +  xr */
         if ((err = ltc_mp_mulmod(s, pubkey.k, p, s)) != CRYPT_OK)     { goto error; } /* s = (e + xr)/k */

This reduces the number of ltc_mp_mulmod() calls from five to two.

However, since b is used as a blinding value, simply removing it would also cause ltc_mp_invmod() to operate directly on the secret ephemeral scalar k. Therefore, I would not suggest removing the blinding unconditionally.

Instead, would it make sense to introduce an optional LTC_ECC_BLINDING configuration define, similar in concept to the existing configurable LTC_RSA_BLINDING support?

For example:

#ifdef LTC_ECC_BLINDING

/* existing blinded implementation */

#else

/* simplified implementation without blinding */

#endif

This could allow applications that require the additional side-channel protection to keep ECC blinding enabled, while applications where this protection is not required could avoid the additional modular multiplications.

Question

Could someone confirm whether the simplified calculation is mathematically equivalent for all supported ECC curves and whether introducing an LTC_ECC_BLINDING configuration option would be a reasonable approach?

If so, it may be possible to reduce the computational cost of ecc_sign_hash_internal when ECC blinding is disabled, while retaining the current blinded implementation for applications that require the additional side-channel protection.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions