++++++++++++++++++++++++ Review of CS255 concepts -- part IV. Digital Signatures ++++++++++++++++++++++++ -------------------------------------------------------------------------- Notes based on CS255, "Introduction to Cryptography", taken Winter '04 and taught by Dr. Dan Boneh - cs255's site: http://crypto.stanford.edu/~dabo/cs255/ -------------------------------------------------------------------------- In the paper world: a signature binds a document to an author main features: anyone can verify, non-repudiation (you can't say you didn't sign it or at least no one will believe you if you do) A signature scheme consists of: (1) key gen: output A_v = verifying key A_s = signing key (2) signature algo: S(M,A_s) (a) D = Hash(M) M maybe 1 MB; D 160 bits (b) S = Sign(D,A_s) (c) output S (3) verify algo: (M,S,A_v) (1) D = Hash(M) (2) Verify(D,S,A_v) (3) Accept if Verify() = "yes" else reject ----------- Definition: ----------- A signature scheme (key gen, sign, verify) is secure if an attacker capable of a chosen-message attack (which is: for any chosen msg, the attacker can get sign(msg)) cannot do existential forgery (which is: construct some (M',s) such that Verify(M',S,A_v) == "yes" and the attacker did not ask for the signature on M'). ---------------------------------------- Constructing Sigs from one-way functions ---------------------------------------- (1) F_M^AES(x) = AES_x(M) Can we build a signature scheme from F^AES? yes. (Lomport, Merkle, Rampel, ...) - but impractical e.g. digest size = 160 bits - choose 320 random values: r_0^1, r_1^1, r_0^2, r_1^2, ..., r_0^160, r_1^160 - each r in {0,1}^512 - Verification key: A_v = { f(r_0^1), f(r_1^1), ..., f(r_0^160), f(r_1^160) } - Signing key: A_s = { the 320 random values from above } - To sign a message m such taht: Hash(M) = h_1 h_2 ... h_160 in {0,1}^160 -- do: sign(m) = take each bit, h_j, of the Hash(M) and if (h_j == 0), then use r_0^j else, use r_1^j - Note: very fast signing - Also note: can only use sign/verif key pair once - can extend this to get full-fledged sig -- first msg = sign plus pub key for 2nd msg -- 2nd msg = sign plus pub key for 3rd msg, ... Can we build sigs out of F^Dlog? Yes, but complicated Can we build sigs out of F^RSA? Yes, very easy b/c of trap door. ----------------------- Signatures based on RSA ----------------------- (1) Full domain hash (FDH) sigs: (a) keygen: - pick n-bit primes p,q N=pq (n=512) - set e = 65,537 --> used for verify; fast - set d = e^-1 mod PHI(N) --> used for signing; slow pubkey = (N,e) privkey = (d) Fix hash function: H : {0,1}* --> Z_N* (b) sign: Sign(M,(d,N)) = H(M)^d mod N = S (c) verify: Test: S^e ?= H(M) mod N It's okay that sign is slow & verify is fast b/c we'll sign once and verification will occur many times. RSA sigs = length of N (typically 128 B) DSS : shorter sigs; so used if bw constraints but no perf constraints Theorem (BR '94): If H : {0,1}* --> Z_N* is an ideal hash function (which is to say, chosen at random from the set of all such hash functions), then FDH-RSA is existentially unforgeable under chosen msg attack assuming RSA-assumption (which is that F^RSA is one-way). Why do we hash message? Needed for security. - Suppose no hash in RSA sigs S = M^d (mod N) (msgs to be signed are elements in Z_N*) Attacks ------- (1) existential forgery given pub key only given: S_0 = M_0^d mod N take: M_1 = (M_0)^e mod N // recall that we have M_0, (N,e), S_0 // so we use those to create M_1 // now the signature for M_1 = M_1^d (mod N) // but M_1 == (M_0)^e so we have: Sig for M_1 = (M_1)^d (mod N) = ( (M_0)^e )^d (mod N) = (M_0)^de (mod N) = M_0 mod N // So M_0 == S_1 == the signature for M_1 // which we were able to forge given just a single valid signature So we have created a valid signature, S_1, on a message, M_1 -- putting aside for the moment whether M_1 makes any sense or is just gobbledygook as an attack implementation concern (2) selective forgery (blinding attack) - using chosen msg attack - adversary wants sig on M in Z_N* (a) pick random r in Z_N* compute: M' = r^e * M mod N (b) request sig on M' get S' = (M')^d mod N = (r^e)^d * M (mod N) = r * M (mod N) (c) set S = S'/r mod N S = r * M / r (mod N) = M mod N Full domain hash: mapping out to entire domain of Z_N* Can't just map out to 160 bits like SHA-1 --------------------------------------- A. Standard RSA sigs in practice: PKCS # 1 --------------------------------------- (1) key gen: generate pubkey, privkey as before (2) sign(m,privkey): (a) D = H(M) H : {0,1}* --> {0,1}^160 (b) define EB: 0x0001 || 11111.......11111100 || D -------------------- this part is 1024 - 160 - 16 bits (c) S = (EB)^d mod N Why use fixed bits (in the middle) instead of random ones? Ans: suppose you used random pad, then the # of valid sigs for a specific msg would be: 2^(1024-160-16) Each of these values would correspond to a valid signature on the message, instead of just one of these values. (3) verify (m,S,pubkey) (1) D = H(M) (2) EB = S^e (mod N) (3) test fixed pad in EB; reject if improperly formatted or o/w invalid (4) test LSBs of EB == D This sig standard has no security analysis but also no attacks.