1# DSA 2 3[TOC] 4 5The digital signature algorithm (DSA) is one of three signature schemes 6descripted in the digital signature standard [DSS]. 7 8## Key generation 9 104.2 Selection of Parameter Sizes and Hash Functions for DSA 11The DSS specifies the following choices for the pair (L,N), 12where L is the size of p in bits and N is the size of q in bits: 13 14L | N 15---:|----: 161024| 160 172048| 224 182048| 256 193072| 256 20 21The tests expect the following properties of the parameters used during 22key generation: 23 24* If only the parameter L is specified by the caller then N should be one 25 of the options proposed in [DSS]. 26* If no size is specified then L should be at least 2048. This is the minimal 27 key size recommended by NIST for the period up to the year 2030. 28 29## Signature generation 30 31The DSA signature algorithm requires that each signature is computed with a new 32one-time secret k. This secret value should be close to uniformly distributed. 33If that is not the case then DSA signatures can leak the private key that was 34used to generate the signature. Two methods for generating the one-time secrets 35are described in FIPS PUB 186-4, Section B.5.1 or B.5.2 [DSS]. There is also the 36possibility that the use of mismatched implementations for key generation and 37signature generation are leaking the private keys. 38 39## Signature verification 40 41A DSA signature is a DER encoded tuple of two integers (r,s). To verify a 42signature the verifier first checks $$0 < r < q$$ and $$0 < s < q$$. The 43verifier then computes: 44 45$$ 46\begin{array}{l} 47w=s^{-1} \bmod q\\ 48u1 = w \cdot H(m) \bmod q\\ 49u2 = w \cdot r \bmod q\\ 50\end{array} 51$$ 52 53and then verifies that \\(r = (g^{u1}y^{u2} \bmod p) \bmod q\\) 54 55## Incorrect computations and range checks. 56 57Some libraries return 0 as the modular inverse of 0 or q. 58This can happen if the library computes the modular 59inverse of s as \\(w=s^{q-2} \mod q\\) (gpg4browsers) of simply 60if the implementations is buggy (pycrypto). if additionally to such 61a bug the range of r,s is not or incorrectly tested then it might 62be feasible to forge signatures with the values (r=1, s=0) or (r=1, s=q). 63In particular, if a library can be forced to compute \\(s^{-1} \mod q = 0\\) 64then the verification would compute \\( w = u1 = u2 = 0 \\) and hence 65\\( (g^{u1}y^{u2} \mod p) \mod q = 1 .\\) 66 67## Timing attacks 68 69TBD 70 71# Some notable failures of crypto libraries. 72 73## JDK 74 75The jdk8 implementation of SHA1withDSA previously checked the key size as follows: 76 77```java 78@Override 79 protected void checkKey(DSAParams params) 80 throws InvalidKeyException { 81 int valueL = params.getP().bitLength(); 82 if (valueL > 1024) { 83 throw new InvalidKeyException("Key is too long for this algorithm"); 84 } 85 } 86``` 87 88This check was reasonable, it partially ensures conformance with the NIST 89standard. In most cases would prevent the attack described above. 90 91However, Oracle released a patch that removed the length verification in DSA in 92jdk9: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/edd7a67585a5 93https://bugs.openjdk.java.net/browse/JDK-8039921 94 95The new code is here: 96http://hg.openjdk.java.net/jdk9/dev/jdk/file/edd7a67585a5/src/java.base/share/classes/sun/security/provider/DSA.java 97 98The change was further backported to jdk8: 99http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/3212f1631643 100 101Doing this was a serious mistake. It easily allowed incorrect implementations. 102While generating 2048 bit DSA keys in jdk7 was not yet supported, doing so in 103jdk8 is. To trigger this bug in jdk7 an application had to use a key generated 104by a third party library (e.g. OpenSSL). Now, it is possible to trigger the bug 105just using JCE. Moreover, the excessive use of default values in JCE makes it 106easy to go wrong and rather difficult to spot the errors. 107 108The bug was for example triggered by the following code snippet: 109 110```java 111 KeyPairGenerator keygen = KeyPairGenerator.getInstance("DSA"); 112 Keygen.initialize(2048); 113 KeyPair keypair = keygen.genKeyPair(); 114 Signature s = Signature.getInstance("DSA"); 115 s.initSign(keypair.getPrivate()); 116``` 117 118The first three lines generate a 2048 bit DSA key. 2048 bits is currently the 119smallest key size recommended by NIST. 120 121```java 122 KeyPairGenerator keygen = KeyPairGenerator.getInstance("DSA"); 123 Keygen.initialize(2048); 124 KeyPair keypair = keygen.genKeyPair(); 125``` 126 127The key size specifies the size of p but not the size of q. The NIST standard 128allows either 224 or 256 bits for the size of q. The selection typically depends 129on the library. The Sun provider uses 224. Other libraries e.g. OpenSSL 130generates by default a 256 bit q for 2048 bit DSA keys. 131 132The next line contains a default in the initialization 133 134```java 135 Signature s = Signature.getInstance("DSA"); 136``` 137This line is equivalent to 138 139```java 140 Signature s = Signature.getInstance("SHA1withDSA"); 141``` 142Hence the code above uses SHA1 but with DSA parameters generated for SHA-224 143or SHA-256 hashes. Allowing this combination by itself is already a mistake, 144but a flawed implementaion made the situation even worse. 145 146The implementation of SHA1withDSA assumeed that the parameter q is 160 bits 147long and used this assumption to generate a random 160-bit k when generating a 148signature instead of choosing it uniformly in the range (1,q-1). 149Hence, k severely biased. Attacks against DSA with biased k are well known. 150Howgrave-Graham and Smart analyzed such a situation [HS99]. Their results 151show that about 4 signatrues leak enough information to determine 152the private key in a few milliseconds. 153Nguyen analyzed a similar flaw in GPG [N04]. 154I.e., Section 3.2 of Nguyens paper describes essentially the same attack as 155used here. More generally, attacks based on lattice reduction were developed 156to break a variety of cryptosystems such as the knapsack cryptosystem [O90]. 157 158## Further notes 159 160The short algorithm name “DSA” is misleading, since it hides the fact that 161`Signature.getInstance(“DSA”)` is equivalent to 162`Signature.getInstance(“SHA1withDSA”)`. To reduce the chance of a 163misunderstanding short algorithm names should be deprecated. In JCE the hash 164algorithm is defined by the algorithm. I.e. depending on the hash algorithm to 165use one would call one of: 166 167```java 168 Signature.getInstance(“SHA1withDSA”); 169 Signature.getInstance(“SHA224withDSA”); 170 Signature.getInstance(“SHA256withDSA”); 171``` 172 173A possible way to push such a change are code analysis tools. "DSA" is in good 174company with other algorithm names “RSA”, “AES”, “DES”, all of which default to 175weak algorithms. 176 177## References 178 179[HS99]: N.A. Howgrave-Graham, N.P. Smart, 180 “Lattice Attacks on Digital Signature Schemes” 181 http://www.hpl.hp.com/techreports/1999/HPL-1999-90.pdf 182 183[N04]: Phong Nguyen, “Can we trust cryptographic software? Cryptographic flaws 184 in Gnu privacy guard 1.2.3”, Eurocrypt 2004, 185 https://www.iacr.org/archive/eurocrypt2004/30270550/ProcEC04.pdf 186 187[O90]: A. M. Odlyzko, "The rise and fall of knapsack cryptosystems", Cryptology 188 and Computational Number Theory, pp.75-88, 1990 189 190[DSS]: FIPS PUB 186-4, "Digital Signature Standard (DSS)", National Institute 191 of Standards and Technology, July 2013 192 http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf 193