英文:
Use Go to encrypt message with ssh-rsa public key which then can be decrypted using openssl rsautl -decrypt
问题
我已经尝试了几天来解决这个问题。在Go代码中,我想要获取一个ssh-rsa公钥,例如:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGnnY4LuLq7Bs7VnFk2Vs6hNTmZLkUBRRhXNFyKZOCvmhKcM7BSHkGS7+phpIzj6mTOsJEBZKHQgac46COOT3ukO/farnnDz78KIq24U/+TZmyAyNNdzOVizK5aAApvpYTQpuSlIDDltLXQkPokedE/5vCIPiwVZW0TfqT/Rdy2XXwKewDQ05xvJhX3+nymZkyJX3GJ+pTfsDkKR+suSLDN3nupThPiWK5A1ZG9bbUkxHbsAXiTKS+qwADIWOtJvfNtPX54JjCo3Gh3/Fy0Ovxn3QSQlCF/IZNbSgm6R6adjaU4kXEF6zsLq+BjDKLtEA3A0tAIBj0T+DuuxpcV3aX
以及消息 hello-world
,并使用该密钥对该消息进行加密。
然后,私钥将用于使用以下命令解密密钥:openssl rsautl -decrypt -inkey privateKeyFile -in encryptedMsgFile
英文:
I have been trying to solve this for days. In Go code I am looking to take a ssh-rsa public key like:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGnnY4LuLq7Bs7VnFk2Vs6hNTmZLkUBRRhXNFyKZOCvmhKcM7BSHkGS7+phpIzj6mTOsJEBZKHQgac46COOT3ukO/farnnDz78KIq24U/+TZmyAyNNdzOVizK5aAApvpYTQpuSlIDDltLXQkPokedE/5vCIPiwVZW0TfqT/Rdy2XXwKewDQ05xvJhX3+nymZkyJX3GJ+pTfsDkKR+suSLDN3nupThPiWK5A1ZG9bbUkxHbsAXiTKS+qwADIWOtJvfNtPX54JjCo3Gh3/Fy0Ovxn3QSQlCF/IZNbSgm6R6adjaU4kXEF6zsLq+BjDKLtEA3A0tAIBj0T+DuuxpcV3aX
and message like: hello-world
and encrypt that message with that key.
The private key is then going to be used to decrypt the key with openssl rsautl -decrypt -inkey privateKeyFile -in encryptedMsgFile
答案1
得分: 1
使用SSH密钥进行加密的详细说明可以在文章Encrypting Data With SSH Keys and Golang中找到,特别是导入OpenSSH公钥的部分,其中使用了ssh包。加密部分(使用PKCS#1 v1.5填充)使用了rsa包。
以下是示例代码。由于OpenSSL语句从文件中读取密文,因此将密文存储在二进制文件中最合理。但为了简单起见,在此示例中,密文以十六进制编码输出:
package main
import (
"crypto/rand"
"crypto/rsa"
"encoding/hex"
"fmt"
"golang.org/x/crypto/ssh"
)
func main() {
// 导入密钥
publicKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8NGcNWf6cUno2lpny36js9ynXCQ6kuJ14yIViuPwty0ZkfhpPdw3zVKWmKV0zS1/QyO6a5d85I9ywvEXHiZr4+fE4JRPxdEIQVGMz7OThs0XgluE4zZrw55ywMt/b6elPC2TkshUHQfDYQuIh1ZBqFOnvUIh8yyGc1L4sLACGY75tpvSE29RZQRmaZaV5YpzIM0SbpFirOqWsjKd3kLMjPqPr9+ISpqOP2tTfOfw9IW8gvRUYa2oRUEyE7Ju4QrwSWmKj9JK9KTeAzRiy5rsSW6issDaxQIYg2BNT8YLrNVm+FWpOVRud6KwohOpk8/YeM0EKEO3vAfGJH6tYT9Zv whatever"
parsed, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKey))
if err != nil {
panic(err)
}
parsedCryptoKey := parsed.(ssh.CryptoPublicKey)
pubCrypto := parsedCryptoKey.CryptoPublicKey()
pub := pubCrypto.(*rsa.PublicKey)
// 加密
msg := "The quick brown fox jumps over the lazy dog"
encryptedBytes, err := rsa.EncryptPKCS1v15(
rand.Reader,
pub,
[]byte(msg),
)
if err != nil {
panic(err)
}
fmt.Println(hex.EncodeToString(encryptedBytes))
}
可能的十六进制编码密文为:
7610da88661fc80b145f3bdd415cb71e73b1ad5100f7b5a9d9c5d27d9e3645d626dd784ccc5cc6c1e44aeec04b0e64072bfe1b58e88feec4b5e6ca63a14c5a23dad1370a303f2f775f4e6f349bab52a3f5883a51ac1f53247a4e05fb9989fc999878ac8f3821da0a079272738145dda7a340b7e4d44d922e563558972444b6f7400a4affffe2a6ee42d400cff51bf3eecc8cd1ffc9ea8c8d04ff6ef0e566d105a4841bcece7b16e2068a321e0c7b4cb964593fcf59795f0a14ec1ac95b941eaa452912bca2e1431992672dcdcc1ea42ff956ef7d21f126a1650c4a306817b4e094ee8c50a01dcc04a7be25e0c01b2ba678be3561774ae859353b5cc98a3b9b11
请注意,此加密是非确定性的,即当您执行代码时,将获得不同的密文。
可以使用以下发布的OpenSSL语句进行解密:
openssl rsautl -decrypt -inkey privateKeyFile -in encryptedMsgFile
需要注意的是:
-
encryptedMsgFile
包含密文的二进制数据,即7610da...
的十六进制解码(如果密文直接存储为二进制文件,如上述提到的,encryptedMsgFile
将对应于此文件)。 -
privateKeyFile
包含PEM编码的私有PKCS#1或PKCS#8密钥。如果您的密钥处于OpenSSH的专有格式(-----BEGIN OPENSSH PRIVATE KEY-----...
),则必须将其转换为PKCS#8格式,例如使用ssh-keygen
:ssh-keygen -p -N "" -m pkcs8 -f data.key
请注意,
data.key
包含OpenSSH密钥,并将被PKCS#8密钥覆盖。对于上述示例,privateKeyFile
如下所示:-----BEGIN PRIVATE KEY----- MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC8NGcNWf6cUno2 lpny36js9ynXCQ6kuJ14yIViuPwty0ZkfhpPdw3zVKWmKV0zS1/QyO6a5d85I9yw vEXHiZr4+fE4JRPxdEIQVGMz7OThs0XgluE4zZrw55ywMt/b6elPC2TkshUHQfDY QuIh1ZBqFOnvUIh8yyGc1L4sLACGY75tpvSE29RZQRmaZaV5YpzIM0SbpFirOqWs jKd3kLMjPqPr9+ISpqOP2tTfOfw9IW8gvRUYa2oRUEyE7Ju4QrwSWmKj9JK9KTeA zRiy5rsSW6issDaxQIYg2BNT8YLrNVm+FWpOVRud6KwohOpk8/YeM0EKEO3vAfGJ H6tYT9ZvAgMBAAECggEBAKP++alNuSpYSDxXAPD86cMLIL9LGiJ46Gb+PBSpYr04 uy8IHz8NW++j2/AtbRQsYuKYpCn/koLE+CJc/GUCSDMaAJLO5FDq4EJAdm0hyNPP Fl28u6Z2qsOu3v8+ZYjIi8+f+xu4/c/kKs0Xgtq+sOdvL+WkBDrR+okhbFErSo3O z4SXkSTbRzKuFuZQA8HPi5kkDloEKhvZr3M0UyxUm6OtQTgW9mz3u+eabtBWVHEk 3CY6AVi+FpKX1wj1j3gYCl5kjAxJALVuPXg/MhuiHBJODWWtsl4qnlrUqVn/qYwW G7GQb9dYjJK+WCjwG0VqoH2egEphaF4BrWMr6DLtseECgYEA5geNRjqKjmfxOlqm mA5BV08tey9C59Ef11aYmrx+ngkKDdHNvY2JOkpEA3huoa0sT4rRylmmYNBUVxnM UVqU8ppwRCfa58KTccopQO3BvSub74GvpwOX9MSn0CzW3brrFPfs72Lo3TAG4png ENufcF1PGqTDFXhQsQC8ZPJmWbECgYEA0XQBcF8tuEN1UHzPwnG35YPayRPusrxd 3PD2BmOcp8B4DHS1KU2vJwu0nisi7S8eUbGxpRjwg3c5clQWFxWHuc//aRRb2QGl TR1XvtnU6qjGAnH7jcF+tsRlWx6Qc35InGodzgS8SzemNzXEOVmI7U4r7LmQe9Q1 SX6dKzp/Gh8CgYB0bzwmYTmDLb/gDsSm0Qhn/k8CPID8QFGCuXWTVXgt3Ft3dUxT 91GP7MmSjCJLuhFkzdq1Nz3NYYZfdFKEl3ovdtb+2MGocEgb3/2TvQVFEM7ko9ta iaogHm7nI9s67wNRYNFQttsyIr5JcyQExHZm9QQ2c1HAC1+kyL+TxVLjcQKBgQC7 g0+Geq9Dt6DfXd3iBkzMfS7xtZaNDXY6xr57GdK1m+ndvN4zDAkyu5gHwjaSgQxz ttGDLMCl8abMY9si73ODNmNCf6d6r659Szey9PFY45/hsIm0bvYyScEzwjkwLG51 Gct1FWg9LqTv6IKzlSSwzrskQzzGn0TVdzTd7pC7oQKBgQDGTj2gvzn4gwFcAQI6 Zs4zbnXWwuQ0zt9y2Nzvs3Qwv8F2uryPnzv8DdbvdZ9dqnZCa8BvEALqfuOpKi4P 5wpd3+Tw6eCwtNZwNZ+TJXLxXelmQBehM52RUb9wM+QzRBhIJayEuveNzJ9Irc14 IDI76VfujESxC/qjZHFXkfdS3A== -----END PRIVATE KEY-----
英文:
Encryption with SSH keys is described in detail in the post Encrypting Data With SSH Keys and Golang, in particular the import of the OpenSSH public key, for which the ssh package is applied. For encryption (with PKCS#1 v1.5 padding) the rsa package is used.
The following sample code illustrates this. Since the OpenSSL statement reads the ciphertext from a file, it makes most sense for the ciphertext to be stored in a binary file. For simplicity, however, in this example the cipher text is output hex encoded:
package main
import (
"crypto/rand"
"crypto/rsa"
"encoding/hex"
"fmt"
"golang.org/x/crypto/ssh"
)
func main() {
// Key import
publicKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC8NGcNWf6cUno2lpny36js9ynXCQ6kuJ14yIViuPwty0ZkfhpPdw3zVKWmKV0zS1/QyO6a5d85I9ywvEXHiZr4+fE4JRPxdEIQVGMz7OThs0XgluE4zZrw55ywMt/b6elPC2TkshUHQfDYQuIh1ZBqFOnvUIh8yyGc1L4sLACGY75tpvSE29RZQRmaZaV5YpzIM0SbpFirOqWsjKd3kLMjPqPr9+ISpqOP2tTfOfw9IW8gvRUYa2oRUEyE7Ju4QrwSWmKj9JK9KTeAzRiy5rsSW6issDaxQIYg2BNT8YLrNVm+FWpOVRud6KwohOpk8/YeM0EKEO3vAfGJH6tYT9Zv whatever"
parsed, _, _, _, err := ssh.ParseAuthorizedKey([]byte(publicKey))
if err != nil {
panic(err)
}
parsedCryptoKey := parsed.(ssh.CryptoPublicKey)
pubCrypto := parsedCryptoKey.CryptoPublicKey()
pub := pubCrypto.(*rsa.PublicKey)
// Encryption
msg := "The quick brown fox jumps over the lazy dog"
encryptedBytes, err := rsa.EncryptPKCS1v15(
rand.Reader,
pub,
[]byte(msg),
)
if err != nil {
panic(err)
}
fmt.Println(hex.EncodeToString(encryptedBytes))
}
A possible hex encoded ciphertext is:
7610da88661fc80b145f3bdd415cb71e73b1ad5100f7b5a9d9c5d27d9e3645d626dd784ccc5cc6c1e44aeec04b0e64072bfe1b58e88feec4b5e6ca63a14c5a23dad1370a303f2f775f4e6f349bab52a3f5883a51ac1f53247a4e05fb9989fc999878ac8f3821da0a079272738145dda7a340b7e4d44d922e563558972444b6f7400a4affffe2a6ee42d400cff51bf3eecc8cd1ffc9ea8c8d04ff6ef0e566d105a4841bcece7b16e2068a321e0c7b4cb964593fcf59795f0a14ec1ac95b941eaa452912bca2e1431992672dcdcc1ea42ff956ef7d21f126a1650c4a306817b4e094ee8c50a01dcc04a7be25e0c01b2ba678be3561774ae859353b5cc98a3b9b11
Note that this encryption is not deterministic, i.e. when you execute the code, you will get a different ciphertext.
Decryption is possible with the posted OpenSSL statement:
openssl rsautl -decrypt -inkey privateKeyFile -in encryptedMsgFile
taking into account:
-
encryptedMsgFile
contains the binary data of the ciphertext, i.e. the hex decoding of7610da...
(if the ciphertext is stored directly as a binary file as mentioned above,encryptedMsgFile
would correspond to this file). -
privateKeyFile
contains the PEM encoded private PKCS#1 or PKCS#8 key. If your key is in OpenSSH's proprietary format (-----BEGIN OPENSSH PRIVATE KEY-----...
), it must be converted to e.g. PKCS#8 format, e.g. withssh_keygen
:ssh-keygen -p -N "" -m pkcs8 -f data.key
Note that
data.key
contains the OpenSSH key and is overwritten with the PKCS#8 key. For the posted example,privateKeyFile
is:-----BEGIN PRIVATE KEY----- MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC8NGcNWf6cUno2 lpny36js9ynXCQ6kuJ14yIViuPwty0ZkfhpPdw3zVKWmKV0zS1/QyO6a5d85I9yw vEXHiZr4+fE4JRPxdEIQVGMz7OThs0XgluE4zZrw55ywMt/b6elPC2TkshUHQfDY QuIh1ZBqFOnvUIh8yyGc1L4sLACGY75tpvSE29RZQRmaZaV5YpzIM0SbpFirOqWs jKd3kLMjPqPr9+ISpqOP2tTfOfw9IW8gvRUYa2oRUEyE7Ju4QrwSWmKj9JK9KTeA zRiy5rsSW6issDaxQIYg2BNT8YLrNVm+FWpOVRud6KwohOpk8/YeM0EKEO3vAfGJ H6tYT9ZvAgMBAAECggEBAKP++alNuSpYSDxXAPD86cMLIL9LGiJ46Gb+PBSpYr04 uy8IHz8NW++j2/AtbRQsYuKYpCn/koLE+CJc/GUCSDMaAJLO5FDq4EJAdm0hyNPP Fl28u6Z2qsOu3v8+ZYjIi8+f+xu4/c/kKs0Xgtq+sOdvL+WkBDrR+okhbFErSo3O z4SXkSTbRzKuFuZQA8HPi5kkDloEKhvZr3M0UyxUm6OtQTgW9mz3u+eabtBWVHEk 3CY6AVi+FpKX1wj1j3gYCl5kjAxJALVuPXg/MhuiHBJODWWtsl4qnlrUqVn/qYwW G7GQb9dYjJK+WCjwG0VqoH2egEphaF4BrWMr6DLtseECgYEA5geNRjqKjmfxOlqm mA5BV08tey9C59Ef11aYmrx+ngkKDdHNvY2JOkpEA3huoa0sT4rRylmmYNBUVxnM UVqU8ppwRCfa58KTccopQO3BvSub74GvpwOX9MSn0CzW3brrFPfs72Lo3TAG4png ENufcF1PGqTDFXhQsQC8ZPJmWbECgYEA0XQBcF8tuEN1UHzPwnG35YPayRPusrxd 3PD2BmOcp8B4DHS1KU2vJwu0nisi7S8eUbGxpRjwg3c5clQWFxWHuc//aRRb2QGl TR1XvtnU6qjGAnH7jcF+tsRlWx6Qc35InGodzgS8SzemNzXEOVmI7U4r7LmQe9Q1 SX6dKzp/Gh8CgYB0bzwmYTmDLb/gDsSm0Qhn/k8CPID8QFGCuXWTVXgt3Ft3dUxT 91GP7MmSjCJLuhFkzdq1Nz3NYYZfdFKEl3ovdtb+2MGocEgb3/2TvQVFEM7ko9ta iaogHm7nI9s67wNRYNFQttsyIr5JcyQExHZm9QQ2c1HAC1+kyL+TxVLjcQKBgQC7 g0+Geq9Dt6DfXd3iBkzMfS7xtZaNDXY6xr57GdK1m+ndvN4zDAkyu5gHwjaSgQxz ttGDLMCl8abMY9si73ODNmNCf6d6r659Szey9PFY45/hsIm0bvYyScEzwjkwLG51 Gct1FWg9LqTv6IKzlSSwzrskQzzGn0TVdzTd7pC7oQKBgQDGTj2gvzn4gwFcAQI6 Zs4zbnXWwuQ0zt9y2Nzvs3Qwv8F2uryPnzv8DdbvdZ9dqnZCa8BvEALqfuOpKi4P 5wpd3+Tw6eCwtNZwNZ+TJXLxXelmQBehM52RUb9wM+QzRBhIJayEuveNzJ9Irc14 IDI76VfujESxC/qjZHFXkfdS3A== -----END PRIVATE KEY-----
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论