DSA and OpenSSH: It’s Legacy, But Still Great

In 1976, Marty Hellman sat at his desk and drafted a method that used discrete logs, and which allowed a shared encryption key to be…

DSA and OpenSSH: It’s Legacy, But Still Great

In 1976, Marty Hellman sat at his desk and drafted a method that used discrete logs, and which allowed a shared encryption key to be created between Bob and Alice. With this, Bob generated a random value of b, and Alice of a, Bob computes B=g^b (mod p) and Alice computes A=g^a (mod p). They exchange values, and then end up with the same key:

The Diffie-Hellman method was thus created around the usage of discrete logarithms. Soon Rivest, Shamir and Adleman followed this work with the RSA encryption method.

So could we create encryption with discrete logs? Well, it was Tahir ElGamal who solved this with the ElGamal encryption method. And could it be used for signatures? Well the DSA (Digital Signature Algorithm) stepped forward.

DSA

The Digital Signature Algorithm (DSA) is a standard defined in Federal Information Processing Standard (as FIPS 186) for digital signatures and is based on discrete logarithms. It was outlined by NIST in 1991, and proposed within the Digital Signature Standard (DSS). This was then standardized with FIPS 186 in 1994, and FIPS 186–4 in 2013. Within FIPS 186–5, it is defined that DSA should not be used for the generation of signatures, but can be used for signature verification. Although DSA has a patent (Patent 5,231,668 by David W. Kravitz, who had previously worked for the NSA), NIST published the standard as royalty-free.

For the DSA keys, we created a private key of x and a prime number of p with a generator of g. The public key is then [Y=g^x (mod p), g, p], and the private key is x.

We can generate DSA keys with:

$ ssh-keygen -t dsa -b 1024 -C "[email protected]"

and which will generate a 1,024-bit key pair. We need at least 1,024 bits for the key, but more likely to use 2,048 or 4,096 bits. Overall, we can use the key pair to log into a remote system. The private key (x) is used to sign a message, and this is checked against the public key (Y, g, p):

We typically store the private key in the ./ssh folder (and id_dsa for the private key and id_dsa.pub for the public key), which contains a public key in the form:

ssh-dss AAAAB3NzaC1kc3MAAACBAINf5THvLt2R8KdCBEhfMCUWsby4
/HAV0LwngUk2sC6ueMv/89XwsQcENVvI+Mdqg1sfw99zakmc7Od1ZlV/
SeoF3hD9PP3D+kn2DoTwc6H6vNTd4rmYXSt7Nwxsmyi3ZV3HpetPO0Mq
LYZjR60o1Xf30Ni16khgDq/mi+5gA6MvAAAAFQD8m/c0flI8gpAcBEg5
vXacyrBqdQAAAIBLa+1OI7v8xPxwnCjibFi2ImdXlHaaTUkk5N7gAU+C
adx79hsHNTYnAv0n0cZ7AOSbG51bTOjFlV43Dh1G5rqgHlJNXxdyJby9
KjqZ0MEkWgFb38NSxxE/iPZpF+RcaVi6IQXplPyDqk8dkbuku+KKEwBY
1FUuYG3fzBrwUD1pkQAAAIADbfwh7OhSE1J0WRaEk/4Usos5Oi6fhUyq
r2u34Ereug9Gt4tkhePab3y31i2PQfsatpR+4VpBC6zpPgHQYpuqlqDR
WJCd+Cxo9751nOiA3xYVxNoiwIn/WxoUkC8Jv8kYFAJRceXkF/auVh77
MUoruAmoT2lGE6zP6ngP2q6jFw==

The private key typically has a PEM form:

-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQCDX+Ux7y7dkfCnQgRIXzAlFrG8uPxwFdC8J4FJNrAurnjL//PV
8LEHBDVbyPjHaoNbH8Pfc2pJnOzndWZVf0nqBd4Q/Tz9w/pJ9g6E8HOh+rzU3eK5
mF0rezcMbJsot2Vdx6XrTztDKi2GY0etKNV399DYtepIYA6v5ovuYAOjLwIVAPyb
9zR+UjyCkBwESDm9dpzKsGp1AoGAS2vtTiO7/MT8cJwo4mxYtiJnV5R2mk1JJOTe
4AFPgmnce/YbBzU2JwL9J9HGewDkmxudW0zoxZVeNw4dRua6oB5STV8XciW8vSo6
mdDBJFoBW9/DUscRP4j2aRfkXGlYuiEF6ZT8g6pPHZG7pLviihMAWNRVLmBt38wa
8FA9aZECgYADbfwh7OhSE1J0WRaEk/4Usos5Oi6fhUyqr2u34Ereug9Gt4tkhePa
b3y31i2PQfsatpR+4VpBC6zpPgHQYpuqlqDRWJCd+Cxo9751nOiA3xYVxNoiwIn/
WxoUkC8Jv8kYFAJRceXkF/auVh77MUoruAmoT2lGE6zP6ngP2q6jFwIVAJMF5kZ+
AUZbUBUpZaPuZ15RL8GF
-----END DSA PRIVATE KEY-----

In the following, we have a DSA key pair for DER format [here]:

Private key encoding:	 Encoding.DER
Private key format: PrivateFormat.PKCS8
Public key encoding: Encoding.DER
Public key format: PublicFormat.SubjectPublicKeyInfo
Curve: DSA
Key size: 1024
Private key:
3082014a0201003082012b06072a8648ce3804013082011e02818100e6f762a4770e0eb6d52582707192bb80cbf51c78ae28edbbcd3807204e5b7fb87ec56c72290ac014f14b8a5142edc8ceafb5f72acd16b73ded02f4c3b6a512c8262d26fd7791828748e7ace139e5d1f218f98a0f2b3972abf46133d1b925ddbb6a50c8f31a307907e9fac3909e0d9c9950720be76cfc086353ff91e1a93ae769021500ac0f971ff1800c54ece1e60d771d85891aa4692d02818010f4fe6f8d2c6e22ca87391aebdc6d22e35a9c4723f7398de2628eb7c2237639f9bbeb16f26f218789c271528ad133b1b3f22e0c6d2a700d36c4c3d38f3e7b042883858d1b5236fd95cd2664bd53c4583145a92ff03067b21da2004a5369261b89d025183296f086d1390179d23b1f69fda97b9a9891dbcd0079106f3206ead104160214634ee4a781e089133b54c30d01bf3756f9cec7ac
Public key:
308201b63082012b06072a8648ce3804013082011e02818100e6f762a4770e0eb6d52582707192bb80cbf51c78ae28edbbcd3807204e5b7fb87ec56c72290ac014f14b8a5142edc8ceafb5f72acd16b73ded02f4c3b6a512c8262d26fd7791828748e7ace139e5d1f218f98a0f2b3972abf46133d1b925ddbb6a50c8f31a307907e9fac3909e0d9c9950720be76cfc086353ff91e1a93ae769021500ac0f971ff1800c54ece1e60d771d85891aa4692d02818010f4fe6f8d2c6e22ca87391aebdc6d22e35a9c4723f7398de2628eb7c2237639f9bbeb16f26f218789c271528ad133b1b3f22e0c6d2a700d36c4c3d38f3e7b042883858d1b5236fd95cd2664bd53c4583145a92ff03067b21da2004a5369261b89d025183296f086d1390179d23b1f69fda97b9a9891dbcd0079106f3206ead1038184000281805d26332645337b3cb82982d1f708e77a28d46965a9a7cef9f452d1fa39fa7867295e06db5bfac96e103b2636e9d8538544d38c1d30b884c79c33d5132897f6ef9ab95c973affb44df9434a6071f0a47839bb435d454efcd8e6acbf4c22cbaaffb60933303bd96d6e23244dfddc3833818414e0a4c6fd4cb5d482d70a14bc5780
== Key details ==
Private key x: 566949463038029484803458682052869802367728404396
Public key Y: 65411605343451730957777234671995236034214926320986927255144039081006419119153114115956761402729552636033782126577976016566329716032648432797695409081341277865562415271646402872439087372081734530311944500353363321573085372207689616603347393645645585367396499832638787174002289640596290950757882636796520322944
Public key p: 162190085870034660130682717039879691549855646934095396056271866326947467300866652335833528341043951766662756032855493125230120866566862906680992805756549627396050155916924271639862014224484602858511725922579041335977233783107955239071296304137680083975744841757106537225640437115199619350222634973285410596713
Public key q: 982294088584616238961009425673231566401849026861
Public key g: 11907615530220677812166687414760608928009050454547361088172396995155182707655331896240326393508919368531467387339418834668285261114237713475098355121960991338706504398334591601017704905988816315783553419994715239294014560177819141790149672857666315463082822119241698832565275626775852028012158248595413723857

and for PEM [here]:

Private key encoding:	 Encoding.PEM
Private key format: PrivateFormat.TraditionalOpenSSL
Public key encoding: Encoding.PEM
Public key format: PublicFormat.SubjectPublicKeyInfo
Curve: DSA
Key size: 1024
Private key:
-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQDXXKHuxa0a+Hrer26z+cgnSZgSpdh1C22ldgpczOqxMvtFMXeg
lEUJmDDIMSvqug/kGxDHSKn0hJghaIpUiU9aPJtiRi4zdFiNOVmlaD3LsBK+yTDr
C6iWbhABfZAZXThZaKWj/I/CL7mRo5nvyhtgOxIb9Dan6Qx6Ppa0p6EWdwIVAIlq
Yt59OSNkD0Le8+bGWIEwBSKXAoGAAORfR3/hBgK5vWMHJ+sgZaz2MYRo3UjuJJ8Z
Xw/PwQnBbz6D+9wnPr26yE5o4orW0Xh3DPLbLlNEQuaUmpxi9Ob1C2K/A8AFm3HU
rIwV11hSNJL9u9xpfePxz7cp3PPk206S2asqb5QpfQrY+BA5iRSgv1+JCsMfTtrt
q0GoBAcCgYEAuudyjGi9VbigTL3aro++/J2z7rZaetubfobWO6t5I7Oc07betTa+
iyF8pkbij2UL7W3SGvirU3KT40Ea6h/WTRG4WR28AT0U51lgX1rHIsu/7Ju/6eqa
eN5P5p1cMInuVUiD5B4NceP3pFyza39P3d+Gy35ZJJ7sVe9+HGk8MfcCFHhmcOfh
gxp1AljsB4FdOS8jiLl/
-----END DSA PRIVATE KEY-----

Public key:
-----BEGIN PUBLIC KEY-----
MIIBtzCCASsGByqGSM44BAEwggEeAoGBANdcoe7FrRr4et6vbrP5yCdJmBKl2HUL
baV2ClzM6rEy+0Uxd6CURQmYMMgxK+q6D+QbEMdIqfSEmCFoilSJT1o8m2JGLjN0
WI05WaVoPcuwEr7JMOsLqJZuEAF9kBldOFlopaP8j8IvuZGjme/KG2A7Ehv0Nqfp
DHo+lrSnoRZ3AhUAiWpi3n05I2QPQt7z5sZYgTAFIpcCgYAA5F9Hf+EGArm9Ywcn
6yBlrPYxhGjdSO4knxlfD8/BCcFvPoP73Cc+vbrITmjiitbReHcM8tsuU0RC5pSa
nGL05vULYr8DwAWbcdSsjBXXWFI0kv273Gl94/HPtync8+TbTpLZqypvlCl9Ctj4
EDmJFKC/X4kKwx9O2u2rQagEBwOBhQACgYEAuudyjGi9VbigTL3aro++/J2z7rZa
etubfobWO6t5I7Oc07betTa+iyF8pkbij2UL7W3SGvirU3KT40Ea6h/WTRG4WR28
AT0U51lgX1rHIsu/7Ju/6eqaeN5P5p1cMInuVUiD5B4NceP3pFyza39P3d+Gy35Z
JJ7sVe9+HGk8Mfc=
-----END PUBLIC KEY-----

== Key details ==
Private key x: 687363403990119008905968703559606616324735285631
Public key Y: 131248516556535542156049004112784484382291626712121200937340280459720200418552741655495937450498274897421747554101735953346718517825924818622952951225404755367990016708512076900475139316223348220130366921747142825246877440148885634453627404282240702549908136468256727965642470074314119412110650322212401983991
Public key p: 151232231203225881490655603441235541569568266199497909192054046567340725205956554273445670255216409833154135791921731408677525637355860454454997442668453514715893387112071278055599083417934481397472115134761190288308286639770103753461216784169497103945186547992884105474108822045205356335583220683396287108727
Public key q: 784504227307067208031380221045200701959862297239
Public key g: 626439069689578950609173624360309099652481666382682966357985428377599901038923127357698455340958645996876693342241438027837288717410163903645094041197501406508673705487306064200763701797359109016596142562311739968815407602836619750644761027337893898842803438532980370089704427217506065971706852833491420167

For an OpenSSL key we get [here]:

Private key encoding:	 Encoding.PEM
Private key format: PrivateFormat.PKCS8
Public key encoding: Encoding.OpenSSH
Public key format: PublicFormat.OpenSSH
Curve: DSA
Key size: 1024
Private key:
-----BEGIN PRIVATE KEY-----
MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBAIWDQt90jv1OW6C6zpdjmaGg73Xq
x+lNC/ZxegzTHTmzhRgj1B0j2m5nB7r5SQRDBSWzwZbqZLRTI8bfFwgjBpHuFpBK
DP7X61ajGWb2gqZGPU8qXstHUlTT3wZOVVoS8kDFSOoRJ097ZzNQX/l3n4STpaFo
/yd0P7ayVm5cW0TnAhUA9JeZ2ybD/5do5qHdmVmxvSKpl48CgYBSvYacj9dFVpl8
UcbajkR0JyTQmOLC/bQW4lnWudp8EeOqi5vX0mvooNCv8qUuZBPWyhlFYzgQgJ/r
BHJSvP/IkaeVibnByZOzriEEwsfPRswenvapYIF5dCxU+rguvn2ZviZCuYoXmuxo
rooqZWsUGKXAGHoEXQD5kjiyLT8O0AQWAhRuUAMNsTBeTbBOe2MUxWuQFqLCUw==
-----END PRIVATE KEY-----

Public key:
ssh-dss AAAAB3NzaC1kc3MAAACBAIWDQt90jv1OW6C6zpdjmaGg73Xqx+lNC/ZxegzTHTmzhRgj1B0j2m5nB7r5SQRDBSWzwZbqZLRTI8bfFwgjBpHuFpBKDP7X61ajGWb2gqZGPU8qXstHUlTT3wZOVVoS8kDFSOoRJ097ZzNQX/l3n4STpaFo/yd0P7ayVm5cW0TnAAAAFQD0l5nbJsP/l2jmod2ZWbG9IqmXjwAAAIBSvYacj9dFVpl8UcbajkR0JyTQmOLC/bQW4lnWudp8EeOqi5vX0mvooNCv8qUuZBPWyhlFYzgQgJ/rBHJSvP/IkaeVibnByZOzriEEwsfPRswenvapYIF5dCxU+rguvn2ZviZCuYoXmuxorooqZWsUGKXAGHoEXQD5kjiyLT8O0AAAAIAPVkMwCpk5rC91eh2LxSheaYesA8wFirk5ZbdW79fIsoK/m+0URpk0fF0BTcHTvqsSaqoho2HfpVevPU8z9/sJCp63ttcOmYKqwE6UufFOGAcNhao+yWuQOmDDtmDvpknRUTfV+rTW3q7twuiCnfhSGlB7cWt3uTqkR3CxJaso1w==
== Key details ==
Private key x: 629773310402557860974683927621963742530353939027
Public key Y: 10769981468620316763336039520233601775487089021323576253107887968207933084473887373646513301826350638925399669156553175785244391571959089167368957380180763001742261703252413699448335562066723599654006998039604874577069650205129402845058845988610380174231547907596375180915668487880097327025329658974322763991
Public key p: 93755833822232228158567108530927940635266308534182777053457260903729730036909066323303374121374680215026945715145106798227351845168427879779295892866589205755439274088916041050087512263454477237374741789590494863789086419764380958319932399265346354789670681982512774149952965421183813036599026541244291171559
Public key q: 1396374563359109228748127255314036761747442472847
Public key g: 58102239325116642494474123515227868979438485535401901064744869637362746457944065203017162202637373065224583400516991794378143944259206150994771701615207249751076667560332247055505231587086843864593613760893430481812765820452409542669884323923120237228736415344901697752350885339879075819648444515541885849296

Coding

The code we can use is:

from cryptography.hazmat.primitives import serialization as crypto_serialization
from cryptography.hazmat.primitives.asymmetric import dsa
from cryptography.hazmat.backends import default_backend as crypto_default_backend
import binascii
import sys
keysize=1024
private_key_encoding= crypto_serialization.Encoding.PEM
# PEM or DER
public_key_encode=0
public_key_form=0
private_key_encode=0
private_key_form=0
private_key_format= crypto_serialization.PrivateFormat.PKCS8
public_key_format= crypto_serialization.PrivateFormat.TraditionalOpenSSL

if (len(sys.argv)>1):
keysize=int(sys.argv[1])
if (len(sys.argv)>2):
private_key_encode=int(sys.argv[2])
if (len(sys.argv)>3):
private_key_form=int(sys.argv[3])
if (len(sys.argv)>4):
public_key_encode=int(sys.argv[4])
if (len(sys.argv)>5):
public_key_form=int(sys.argv[5])

if (private_key_encode==0):
private_key_encoding= crypto_serialization.Encoding.DER
elif (private_key_encode==1):
private_key_encoding= crypto_serialization.Encoding.PEM
else:
private_key_encoding= crypto_serialization.Encoding.OpenSSH
if (private_key_form==0):
private_key_format= crypto_serialization.PrivateFormat.PKCS8
elif (private_key_form==1):
private_key_format= crypto_serialization.PrivateFormat.OpenSSH
else:
private_key_format= crypto_serialization.PrivateFormat.TraditionalOpenSSL
if (public_key_encode==0):
public_key_encoding= crypto_serialization.Encoding.DER
elif (public_key_encode==1):
public_key_encoding= crypto_serialization.Encoding.PEM
else:
public_key_encoding= crypto_serialization.Encoding.OpenSSH
if (public_key_form==0):
public_key_format= crypto_serialization.PublicFormat.SubjectPublicKeyInfo
elif (public_key_form==1):
public_key_format= crypto_serialization.PublicFormat.OpenSSH

key = dsa.generate_private_key(
backend=crypto_default_backend(),
key_size=keysize
)
try:
print("Private key encoding:\t",private_key_encoding)
print("Private key format:\t",private_key_format)
print("Public key encoding:\t",public_key_encoding)
print("Public key format:\t",public_key_format)
print("Curve:\t\t\tDSA")
print(f"Key size:\t\t{keysize}")

private_key = key.private_bytes(private_key_encoding,private_key_format,crypto_serialization.NoEncryption())
if (private_key_encoding== crypto_serialization.Encoding.DER or private_key_encoding== crypto_serialization.Encoding.Raw):
print(f"\nPrivate key:\n{binascii.b2a_hex(private_key).decode()}")
else:
print(f"\nPrivate key:\n{private_key.decode()}")
except Exception as e:
print("Private key error: ",e)
try:
public_key = key.public_key().public_bytes(public_key_encoding,public_key_format)
if (public_key_encoding== crypto_serialization.Encoding.DER or public_key_encoding== crypto_serialization.Encoding.Raw):
print(f"\nPublic key:\n{binascii.b2a_hex(public_key).decode()}")
else:
print(f"\nPublic key:\n{public_key.decode()}")
except Exception as e:
print("\nPublic key error: ",e)
print("\n== Key details ==")
print(f"Private key x: {key.private_numbers().x}")
print(f"Public key Y: {key.private_numbers().public_numbers.y}")
print(f"Public key p: {key.private_numbers().public_numbers.parameter_numbers.p}")
print(f"Public key q: {key.private_numbers().public_numbers.parameter_numbers.q}")
print(f"Public key g: {key.private_numbers().public_numbers.parameter_numbers.g}"))

Conclusions

RSA is still very much in use in encryption and signatures, and ECDSA and EdDSA are for signatures, but DSA is not used much now. In fact, it is only supported for legacy applications, and will eventually be dropped in the FIPS 186 standard. The great thing that DSA did, was the conversion of the version to elliptic curves and the usage of ECDSA (as used in Bitcoin and Ethereum). DSA should not be used to create new signatures, and only to check them.

Want to know more about the DSA method? Try here …

https://asecuritysite.com/dsa