/* sign.c - ESIGN Signature Generation Copyright NTT MCL, 2000. Duncan S Wong Security Group, NTT MCL July 2000 */ #include #include #include "esign.h" #include "hash.h" #include "utils.h" #include "random.h" /* ESIGN Signature Generation Return: TRUE if succeed; otherwise FALSE */ BYTE ESIGN_Sign ( BYTE *message, WORD mLen, ESIGN_PUB_KEY *publicKey, ESIGN_PRIV_KEY *privateKey, BYTE *signature ) { RANDOM_STRUCT randomStruct; unsigned int bytesNeeded; static unsigned char seedByte = 0; mpz_t r, gcd_val, m, z, alpha, w0, w1, pq, t, S; size_t w1_size; /* the size of w1 is in # bits */ BYTE *r_raw, *m_raw, *z_raw, *H_out; long i; mpz_init(r); mpz_init(gcd_val); mpz_init(m); mpz_init(z); mpz_init(alpha); mpz_init(w0); mpz_init(w1); mpz_init(pq); mpz_init(t); mpz_init(S); r_raw = (BYTE *) malloc (publicKey->pLen*2/8); m_raw = (BYTE *) malloc (mLen/8); z_raw = (BYTE *) malloc (publicKey->pLen*3/8); H_out = (BYTE *) malloc (publicKey->pLen/8); /* initialize random number generator */ RandomInit(&randomStruct); /* initialize with all zero seed bytes for testing purpose only */ while (1) { GetRandomBytesNeeded (&bytesNeeded, &randomStruct); if (bytesNeeded == 0) break; RandomUpdate (&randomStruct, &seedByte, 1); } /* prepare (mpz_t) m and (BYTE *) m_raw */ mpz_set_str(m, message, 0); WORD2BYTE(m_raw, m->_mp_d, ABS(m->_mp_size)); /* H'(M) and set it to 0||H(M) */ indexedSHA(H_out, publicKey->pLen/8, m_raw, mLen/8); H_out[0] = H_out[0] & 0x7F; /* construct z := (0||H(M)||0^{2*pLen}) */ memset(z_raw, 0, publicKey->pLen*3/8); assignBYTE(z_raw, H_out, publicKey->pLen/8); BYTE2WORD(z, z_raw, publicKey->pLen*3/8); /* printf("ESIGN_Sign: z=\n%s\n\n", mpz_get_str(NULL, 16, z)); */ mpz_mul(pq, privateKey->p, privateKey->q); do { /* randomly choose r \in Z_pq\pZ */ do { GenerateBytes(r_raw, publicKey->pLen*2/8, &randomStruct); BYTE2WORD(r, r_raw, publicKey->pLen*2/8); mpz_mod(r, r, pq); mpz_gcd(gcd_val, r, privateKey->p); } while (mpz_cmp_ui(gcd_val, 1) != 0); /* compute alpha := (z - r^e) mod n */ mpz_powm(alpha, r, publicKey->e, publicKey->n); mpz_sub(alpha, z, alpha); mpz_mod(alpha, alpha, publicKey->n); /* compute w_0 := \ceiling{alpha/(pq)} and w1 := w0*pq - alpha */ mpz_tdiv_qr(w0, w1, alpha, pq); if(mpz_cmp_ui(w1, 0) != 0) { mpz_add_ui(w0, w0, 1); mpz_sub(w1, pq, w1); } w1_size = mpz_sizeinbase(w1, 2); } while (w1_size >= 2*publicKey->pLen-1); printf("r = 0x%s\n", mpz_get_str(NULL, 16, r)); /* printf("ESIGN_Sign: alpha =\n%s\n\n", mpz_get_str(NULL, 16, alpha)); printf("ESIGN_Sign: w0=\n%s\n\n", mpz_get_str(NULL, 16, w0)); printf("ESIGN_Sign: w1=\n%s\n\n", mpz_get_str(NULL, 16, w1)); */ /* compute t := w0 * (e * r^(e-1))^{-1} mod p */ mpz_sub_ui(t, publicKey->e, 1); mpz_powm(t, r, t, privateKey->p); mpz_mul(t, publicKey->e, t); mpz_invert(t, t, privateKey->p); mpz_mul(t, w0, t); mpz_mod(t, t, privateKey->p); /* compute S := (r + tpq) mod n */ mpz_mul(S, t, pq); mpz_add(S, r, S); mpz_mod(S, S, publicKey->n); /* printf("ESIGN_Sign: S=\n%s\n\n", mpz_get_str(NULL, 16, S)); */ sprintf(signature, "0x%s", mpz_get_str(NULL, 16, S)); /* clean up */ memset(r_raw, 0, publicKey->pLen*2/8); memset(m_raw, 0, mLen/8); memset(z_raw, 0, publicKey->pLen*3/8); memset(H_out, 0, publicKey->pLen/8); free(r_raw); free(m_raw); free(z_raw); free(H_out); mpz_clear(r); mpz_clear(gcd_val); mpz_clear(m); mpz_clear(z); mpz_clear(alpha); mpz_clear(w0); mpz_clear(w1); mpz_clear(pq); mpz_clear(t); mpz_clear(S); w1_size = 0; return TRUE; }