static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen) { struct dss_key *dss = (struct dss_key *) key; Bignum k, gkp, hash, kinv, hxr, r, s; unsigned char digest[20]; unsigned char *bytes; int nbytes, i; SHA_Simple(data, datalen, digest); k = dss_gen_k("DSA deterministic k generator", dss->q, dss->x, digest, sizeof(digest)); kinv = modinv(k, dss->q); /* k^-1 mod q */ assert(kinv); /* * Now we have k, so just go ahead and compute the signature. */ gkp = modpow(dss->g, k, dss->p); /* g^k mod p */ r = bigmod(gkp, dss->q); /* r = (g^k mod p) mod q */ freebn(gkp); hash = bignum_from_bytes(digest, 20); hxr = bigmuladd(dss->x, r, hash); /* hash + x*r */ s = modmul(kinv, hxr, dss->q); /* s = k^-1 * (hash + x*r) mod q */ freebn(hxr); freebn(kinv); freebn(k); freebn(hash); /* * Signature blob is * * string "ssh-dss" * string two 20-byte numbers r and s, end to end * * i.e. 4+7 + 4+40 bytes. */ nbytes = 4 + 7 + 4 + 40; bytes = snewn(nbytes, unsigned char); PUT_32BIT(bytes, 7); memcpy(bytes + 4, "ssh-dss", 7); PUT_32BIT(bytes + 4 + 7, 40); for (i = 0; i < 20; i++) { bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i); bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i); } freebn(r); freebn(s); *siglen = nbytes; return bytes; }
static void ecdsa_sign(ssh_key *key, ptrlen data, unsigned flags, BinarySink *bs) { struct ecdsa_key *ek = container_of(key, struct ecdsa_key, sshk); const struct ecsign_extra *extra = (const struct ecsign_extra *)ek->sshk.vt->extra; assert(ek->privateKey); mp_int *z = ecdsa_signing_exponent_from_data(ek->curve, extra, data); /* Generate k between 1 and curve->n, using the same deterministic * k generation system we use for conventional DSA. */ mp_int *k; { unsigned char digest[20]; hash_simple(&ssh_sha1, data, digest); k = dss_gen_k( "ECDSA deterministic k generator", ek->curve->w.G_order, ek->privateKey, digest, sizeof(digest)); } WeierstrassPoint *kG = ecc_weierstrass_multiply(ek->curve->w.G, k); mp_int *x; ecc_weierstrass_get_affine(kG, &x, NULL); ecc_weierstrass_point_free(kG); /* r = kG.x mod order(G) */ mp_int *r = mp_mod(x, ek->curve->w.G_order); mp_free(x); /* s = (z + r * priv)/k mod n */ mp_int *rPriv = mp_modmul(r, ek->privateKey, ek->curve->w.G_order); mp_int *numerator = mp_modadd(z, rPriv, ek->curve->w.G_order); mp_free(z); mp_free(rPriv); mp_int *kInv = mp_invert(k, ek->curve->w.G_order); mp_free(k); mp_int *s = mp_modmul(numerator, kInv, ek->curve->w.G_order); mp_free(numerator); mp_free(kInv); /* Format the output */ put_stringz(bs, ek->sshk.vt->ssh_id); strbuf *substr = strbuf_new(); put_mp_ssh2(substr, r); put_mp_ssh2(substr, s); put_stringsb(bs, substr); mp_free(r); mp_free(s); }