2

I'm looking for a Linux/Unix command-line tool to create a DSA signature from a given file/data and a private key.

I know about the xmlsec1 tool. But I would like something simpler. It seems that OpenSSL provides this function as a developer library, but not as a tool.

user1868607
  • 103
  • 4
mparaz
  • 159
  • 1
  • 7

4 Answers4

3

It's done with "openssl dgst" - not the most obvious place to put it...

Found in:

http://www.myelin.co.nz/post/2005/5/23/

openssl dsaparam 1024 < /dev/random > dsaparam.pem

openssl gendsa dsaparam.pem -out dsa_priv.pem

openssl dsa -in dsa_priv.pem -pubout -out dsa_pub.pem

echo "foobar" > foo.txt

sha1sum < foo.txt | awk '{print $1}' > foo.sha1

openssl dgst -dss1 -sign dsa_priv.pem foo.sha1 > sigfile.bin

openssl dgst -dss1 -verify dsa_pub.pem -signature sigfile.bin foo.sha1
mparaz
  • 159
  • 1
  • 7
  • 1
    Late but: `dgst -sign/verify` hashes _and_ PK-signs/verifies (including DSA), so your sequence actually double-hashes, which is equally secure but not standard/interoperable. Effective with OpenSSL 1.0.0 (released 2010) you no longer need the `-dss1` hack, you can use `-sha1` with a DSA key -- and `-sha224` and `-sha256` for the larger DSA sizes specified by FIPS 186-3 and later (which officially became mandatory for USgovt as of 2014). – dave_thompson_085 Jul 23 '17 at 05:33
  • @dave_thompson_085: Thanks for your note! I've made a tentative modern and correct alternative [there](https://serverfault.com/a/934007/183704), but it needs to be vetted. – fgrieu Oct 04 '18 at 16:21
1

The following tentative set of commands seems to work with openssl 1.0.2g and 1.1.0g. Compared to that other answer, it aims to generate a signature of the file (including the standard-mandated hash step), rather than a signature (including a second hash step) of the lowercase hexadecimal ASCII representation of a first hash of the file. Also it uses more modern hash and modulus size.

# generate parameters with 2048-bit DSA, SHA-256 (can be common to multiple keys)
openssl genpkey -genparam -algorithm DSA -pkeyopt dsa_paramgen_bits:2048 -pkeyopt dsa_paramgen_q_bits:256 -pkeyopt dsa_paramgen_md:sha256 -out dsaparams.pem

# generate a private key and extract the public key
openssl genpkey -paramfile dsaparams.pem -out dsaprivkey.pem
openssl dsa -in dsaprivkey.pem -pubout > dsapubkey.pem

# create a file "myfile" to be signed
echo 'The Magic Words are Squeamish Ossifrage' > myfile

# create signature "myfile.sig"
openssl dgst -sha256 -sign dsaprivkey.pem myfile > myfile.sig

# verify "myfile" against signature "myfile.sig" and public key
openssl dgst -sha256 -verify dsapubkey.pem -signature myfile.sig myfile

Note: A former attempt made openssl 1.0.2g generate signatures with 160-bit q (perhaps using SHA-1). Per comment, I added -sha256 to openssl dgst, but it made no difference. Experiments suggest it is necessary to use -pkeyopt dsa_paramgen_q_bits:256, even though the man page explicitly states -pkeyopt dsa_paramgen_md:sha256 takes care of that:

dsa_paramgen_md:digest
The digest to use during parameter generation. Must be one of sha1, sha224 or sha256. If set, then the number of bits in q will match the output size of the specified digest and the dsa_paramgen_q_bits parameter will be ignored (..)

fgrieu
  • 355
  • 4
  • 17
  • 1
    Since you didn't specify the hash, in 1.0.2 (and down to 1.0.0) `dgst` defaults to MD5 -- and no standard ever defined/allowed DSA with MD5, so this probably won't interop (though OpenSSL-to-OpenSSL works). 1.1.0 (and now 1.1.1) defaults to SHA256 and DSA+SHA256 (for p-size 2k or 3k) is standard since 186-3 in 2008 -- although some implementations lagged; Sun/Oracle/OpenJDK Java didn't support this until j8 in 2014, and today in 2018 SO still gets Qs from people stuck on 7 or even 6 or 5. Personally I'd specify it for clarity even when the default is good. – dave_thompson_085 Oct 06 '18 at 23:21
  • @dave_thompson_085: Thanks for having checked! Indeed my former script did not work as intended: the signature generated by openssl 1.0.2g had two components of 160 bits (or slightly less), which suggests the use of SHA-1 (or a smaller hash such as MD5). I added `-sha256` to `openssl dgst` but if it made no difference in the signature format. I hope I nailed down the issue to `dsa_paramgen_md:sha256` not forcing `dsa_paramgen_q_bits:256` despite what the man page states. I have left `-sha256` in `openssl dgst` but I'm unsure of what that does. – fgrieu Oct 07 '18 at 06:58
  • r,s in DSA signature are mod q, and thus the same size or slightly smaller, NOT the size of the hash used if that is different; see 186-3 (or 4) 4.6, 4.7 and 4.2 which _recommends_ in effect hash size = q size (called N) but explicitly does not require it. OpenSSL 1.1.0 up `EVP_PKEY_{sign,verify}*` used by `pkeyutl -sign/verify` does check that the provided data size matches the _specified_ hash (even though it doesn't actually perform that hash) – dave_thompson_085 Oct 07 '18 at 22:49
  • Yes, dsa_paramgen_md does not set q size; the genpkey man page is clearly wrong. (It _almost_ describes the behavior of the old DSA_generate* API used by `gendsa` NOT the EVP_PKEY[_CTX] one used by `genpkey`.) In fact checking the source it doesn't even work in 1.0.0 1.0.1 1.0.2 below k and 1.1.0 below d. But since OpenSSL doesn't store the seed,count values that could be used for parameter validation, it doesn't actually matter what the paramgen hash is. – dave_thompson_085 Oct 07 '18 at 23:09
0

Have you looked at:

Dennis Williamson
  • 60,515
  • 14
  • 113
  • 148
0

Do you want to create a signature for a file such that the integrity of that file can be verified? I think you're looking for Gnu Privacy Guard (GnuPG).

gpg --output filename.sig --detach-sig filename

This creates a signature file, filename.sig, based on the original, filename, that can be verified with

gpg --verify filename.sig filename
dotplus
  • 1,220
  • 7
  • 12
  • Was looking for something simpler, just using the DSA private key without GPG infrastructure, but let me see if this will do. – mparaz Jan 09 '11 at 08:50