【问题标题】:Generate DSA Keys for OpenSSH in Golang在 Golang 中为 OpenSSH 生成 DSA 密钥
【发布时间】:2022-01-20 04:19:58
【问题描述】:

我通读了几个示例以在 Go 中为 OpenSSH 生成 DSA 密钥。下面列出了我的干净代码 sn-p 和输出。

它有两个问题:

  1. 对于 2048 位长度,无法通过 ssh.ParseAuthorizedKey 加载公钥,错误:“ssh: no key found”。
  2. OpenSSH 客户端和 GitHub SSH 无法接受。

代码sn-ps:

// GenerateDSAKeys generates DSA public and private key pair with given size for SSH.
func GenerateDSAKeys(bitSize int, passphrase string) (pubKey string, privKey string, err error) {
    params := new(dsa.Parameters)

    // see http://golang.org/pkg/crypto/dsa/#ParameterSizes
    if err = dsa.GenerateParameters(params, rand.Reader, dsaSizeFromLength(bitSize)); err != nil {
        return
    }

    var privateKey dsa.PrivateKey
    privateKey.PublicKey.Parameters = *params

    // this generates a public & private key pair
    if err = dsa.GenerateKey(&privateKey, rand.Reader); err != nil {
        return
    }

    // generate public key
    var publicKey ssh.PublicKey
    if publicKey, err = ssh.NewPublicKey(&privateKey.PublicKey); err != nil {
        return
    }

    // encode public key
    pubBytes := ssh.MarshalAuthorizedKey(publicKey)

    // encode private key
    var (
        bytes     []byte
        privBytes []byte
    )
    if bytes, err = asn1.Marshal(privateKey); err != nil {
        return
    }
    privBytes, err = encodePEMBlock(&pem.Block{
        Type:  "DSA PRIVATE KEY",
        Bytes: bytes,
    }, passphrase)
    if err != nil {
        return
    }

    return string(pubBytes), string(privBytes), nil
}

func dsaSizeFromLength(l int) dsa.ParameterSizes {
    switch l {
    case 1024:
        return dsa.L1024N160
    case 2048:
        return dsa.L2048N224
    case 3072:
        return dsa.L3072N256
    default:
        return dsa.L2048N256
    }
}

1024 的输出:

bash-3.2$ cat id_dsa.pub
ssh-dss AAAAB3NzaC1kc3MAAACBAIbuW6wh5hU2W96tEyo7xPDZmslWnsyQBYtf4SSTeHOMTNTxznlMujjkmCuqKJ04BlHFi+ner2qzCd1GkzGhHrretQw1z5Ew8ysAGsmbb9Yc6BMTyhJkrQ2lIR5Vmqa9Ukx0PM/HdXa6GieYZWxyabN5IjN4SESXZ6G7Jb4StwCfAAAAFQCnj+WurTgW5aXGYePwhBYAWX01WwAAAIBHQpZSsJGKsEII7Oe6RMz5ek27ydHPnrLDqVOmEKqHrIrsYXoTHaMOLW+fvsDBC3q0EWMBNgu4IAZe3eL2Gx2r94+DS+GTfECWiJ3+O76DTAwDcB6fXxdYxG88nJMzCkcMZEmOjbIpuiGP5NC+OOqBv2DEHw7YEWs8Kx4T71mE0AAAAIEAhg/OB98FTcYX/gXEclKqqDByHzHIt71Y7DFZnxnmd4DFEZp/WzJ6VT2jTNMyWKRT9h0SITORLKNxTCM3ZLhQYVBinOsjIzZ8YlYYOxTn2mWntWzmsdhUeBx+aNCwuhz/cMHjbhWJWVXRDfgzPf9IHtF1FLgjtMiz6/xwzAMEPlE= vej@Vej-Work-MBP.local
bash-3.2$ cat id_dsa
-----BEGIN DSA PRIVATE KEY-----
MIIBwDCCAaYwggEeAoGBAIbuW6wh5hU2W96tEyo7xPDZmslWnsyQBYtf4SSTeHOM
TNTxznlMujjkmCuqKJ04BlHFi+ner2qzCd1GkzGhHrretQw1z5Ew8ysAGsmbb9Yc
6BMTyhJkrQ2lIR5Vmqa9Ukx0PM/HdXa6GieYZWxyabN5IjN4SESXZ6G7Jb4StwCf
AhUAp4/lrq04FuWlxmHj8IQWAFl9NVsCgYBHQpZSsJGKsEII7Oe6RMz5ek27ydHP
nrLDqVOmEKqHrIrsYXoTHaMOLW+fvsDBC3q0EWMBNgu4IAZe3eL2Gx2r94+DS+GT
fECWiJ3+O76DTAwDcB6fXxdYxG88nJMzCkcMZEmOjbIpuiGP5NC+OOqBv2DEHw7Y
EWs8Kx4T71mE0AKBgQCGD84H3wVNxhf+BcRyUqqoMHIfMci3vVjsMVmfGeZ3gMUR
mn9bMnpVPaNM0zJYpFP2HRIhM5Eso3FMIzdkuFBhUGKc6yMjNnxiVhg7FOfaZae1
bOax2FR4HH5o0LC6HP9wweNuFYlZVdEN+DM9/0ge0XUUuCO0yLPr/HDMAwQ+UQIU
RhBIeYLqxL4PJgENdgtjfjxDX80=
-----END DSA PRIVATE KEY-----

对于 2048,输出:

bash-3.2$ cat id_dsa.pub
ssh-dss AAAAB3NzaC1kc3MAAAEBAKbfrtje1KqerXL0DFg35Ouou2NP08vsuqCbv/cr65X2/AMaDy/Zdikq1rHw1ScWzre0vGTDwnGsFJgNDf3p0ckJqxMN9kop+8a+M1nuQ39LnkHATM+x58jgJaC06VZisLQuMoJvzdOlMPKb1v9TKfSiI0XZujhS5RVl4DkqABEXFsNXOHTIGDXToq80IPf0KV01qvOGBnICzhPkXw5HcCF9rmVD5aPfADjHZfUTt9PJfFcPk06mmfvpOEBfWgaluIDp0Wf5DsKu0RxlZVm4x3iP43hQfJ8NaFRyOKhNxd0r5t5SDUubF2Z37v0QNIvLZPrKsE0AywNkDZ66bf3HigMAAAAdAMjEhWBLtQ+nWfJIO16rpLQZQKBpXePefLrztpUAAAEALJsfHywD5PSfeFUGs901I1Z/yvOuyHQFxJGXEAQJ08CBAGvwcGA1M41sDnbrbOFm8ol91xcnUqW0HMlwDpdHIBxgytlnKlsEw69GqCx1dJAv8LnDokK/zV406I0LLwXzQ3QvfSMtM3VDsIA/jInd273LlXFEG4dmkG1mIP7SBgbzy7jZ4LpH5y8ZSUMFlZ4dXTURj4TAe/ByScaXoVO8QDLaZq5EiSRAomUxLvnwTNJHt/YqQog5EWhQNBUKp5HbPS7pk+KujaUpYwXNZZuhqjp4dmaBYppwCZnrqvsHKq6p8BCt4ZQ/589q0D1Mx0pbgI/sQLvib5jSHJ0jKq7xrAAAAQBzxG2gTr89VeVJBMsconclvXw7vYDxQGBGhZBmKQ6e/s8swxJzzUbpRzoeYGEL1nE28e4Apw6pQFY3XkuvklYTwNHPLwG/5FJV7fc2HJgwVg8/wf5hUrzqlKK9Xhjm2369iKnGig/u28e79oOWgdbqfrjWpNih/aVL60ApdWgxmxC61PGppJ2AXNubaDynhMOx1q+lSH+unu+kLml+c+lbqwZYXmI0t+gFzyyu+pL8DpVEhAG8P/AMCXMDR3JmQhWF7fKiP1QdDMidUODM8keVQaK5txIp9EUAThk0ErigG5ZsIL5V2Z4UistlwQ4WiZYJmz/IlD50+PtkjwBFiA6z vej@Vej-Work-MBP.local
bash-3.2$ cat id_dsa
-----BEGIN DSA PRIVATE KEY-----
MIIDUzCCAzAwggIoAoIBAQCm367Y3tSqnq1y9AxYN+TrqLtjT9PL7Lqgm7/3K+uV
9vwDGg8v2XYpKtax8NUnFs63tLxkw8JxrBSYDQ396dHJCasTDfZKKfvGvjNZ7kN/
S55BwEzPsefI4CWgtOlWYrC0LjKCb83TpTDym9b/Uyn0oiNF2bo4UuUVZeA5KgAR
FxbDVzh0yBg106KvNCD39CldNarzhgZyAs4T5F8OR3Ahfa5lQ+Wj3wA4x2X1E7fT
yXxXD5NOppn76ThAX1oGpbiA6dFn+Q7CrtEcZWVZuMd4j+N4UHyfDWhUcjioTcXd
K+beUg1Lmxdmd+79EDSLy2T6yrBNAMsDZA2eum39x4oDAh0AyMSFYEu1D6dZ8kg7
XquktBlAoGld4958uvO2lQKCAQAsmx8fLAPk9J94VQaz3TUjVn/K867IdAXEkZcQ
BAnTwIEAa/BwYDUzjWwOduts4WbyiX3XFydSpbQcyXAOl0cgHGDK2WcqWwTDr0ao
LHV0kC/wucOiQr/NXjTojQsvBfNDdC99Iy0zdUOwgD+Mid3bvcuVcUQbh2aQbWYg
/tIGBvPLuNngukfnLxlJQwWVnh1dNRGPhMB78HJJxpehU7xAMtpmrkSJJECiZTEu
+fBM0ke39ipCiDkRaFA0FQqnkds9LumT4q6NpSljBc1lm6GqOnh2ZoFimnAJmeuq
+wcqrqnwEK3hlD/nz2rQPUzHSluAj+xAu+JvmNIcnSMqrvGsAoIBAHPEbaBOvz1V
5UkEyxyidyW9fDu9gPFAYEaFkGYpDp7+zyzDEnPNRulHOh5gYQvWcTbx7gCnDqlA
VjdeS6+SVhPA0c8vAb/kUlXt9zYcmDBWDz/B/mFSvOqUor1eGObbfr2IqcaKD+7b
x7v2g5aB1up+uNak2KH9pUvrQCl1aDGbELrU8amknYBc25toPKeEw7HWr6VIf66e
76QuaX5z6VurBlheYjS36AXPLK76kvwOlUSEAbw/8AwJcwNHcmZCFYXt8qI/VB0M
yJ1Q4MzyR5VBorm3Ein0RQBOGTQSuKAblmwgvlXZnhSKy2XBDhaJlgmbP8iUPnT4
+2SPAEWIDrMCHQDGpe828eiBg56q0tQup2r3UpgiXevRNEuF0Gbw
-----END DSA PRIVATE KEY-----

你能告诉我如何解决它,并让它工作吗?

【问题讨论】:

  • 您为什么不能使用 RSA 密钥?大多数密码系统已切换到 RSA 以获得更大的密钥长度。可能它们不支持 2048 位(及更高)域参数。

标签: go ssh cryptography openssh dsa


【解决方案1】:

OpenSSH 在 5 年前默认停止支持 DSA(又名 ssh-dss);见
https://security.stackexchange.com/questions/112802/why-openssh-deprecated-dsa-keys
https://security.stackexchange.com/questions/146379/does-ssh-support-dsa-with-2048-bit-keys
https://superuser.com/questions/1016989/ssh-dsa-keys-no-longer-work-
https://unix.stackexchange.com/questions/247612/ssh-keeps-skipping-my-pubkey-
您可以按照 Qs 或 openssh 网站或文档中的说明在您的客户端上重新启用它,但是 github won't accept it 所以您无法使其正常工作。 (您可以设置自己的服务器,并在那里使用它。)

我不知道为什么某些 go 代码(库?)不接受 2048 位公钥——如果你提供参考,我可以尝试查看——但是(两者)你的 私钥 em> 文件不正确,我猜是由于链接中显示的crypto/dsa 中使用的结构。关键是作为嵌套序列被编组(序列化)到 ASN.1,即 SEQUENCE { pub = SEQUENCE { params = SEQUENCE {p,q,g}, y }, x } 这在概念上是一个合理的结构,但是 PEM (或伪 PEM)类型 DSA PRIVATE KEY 实际上由 SSLeay-now-OpenSSL 定义为使用单个级别:SEQUENCE { p,q,g, y, x } 。

【讨论】: