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.


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

Found in:


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
  • 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 5:33
  • @dave_thompson_085: Thanks for your note! I've made a tentative modern and correct alternative there, but it needs to be vetted. – fgrieu Oct 4 '18 at 16:21

Have you looked at:

  • Yes, these manage the keys, but don't encrypt/decrypt. – mparaz Jan 9 '11 at 8:44

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
  • Was looking for something simpler, just using the DSA private key without GPG infrastructure, but let me see if this will do. – mparaz Jan 9 '11 at 8:50

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:

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 (..)

  • 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 6 '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 7 '18 at 6: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 7 '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 7 '18 at 23:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.