Openpgp security update (V2) (#31)
* Change keyring unlock functionalities * Add keyring#Lock, keyring#CheckIntegrity, tests * Update helpers, fix bugs * Update go.mod with ProtonMail/crypto commit * Change key management system * Clear keys from memory + tests * Create SessionKey with direct encryption for datapackets. Move symmetrickey to password. * Fix upstream dependencies * Update module to V2, documentation * Add linter * Add v2 folder to .gitignore * Minor changes to KeyID getters * Remove old changelog * Improve docs, remove compilation script
This commit is contained in:
parent
136c0a5495
commit
54f45d0471
46 changed files with 2588 additions and 1770 deletions
|
|
@ -3,12 +3,14 @@ package helper
|
|||
import (
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
)
|
||||
|
||||
var err error
|
||||
const testTime = 1557754627 // 2019-05-13T13:37:07+00:00
|
||||
|
||||
func readTestFile(name string, trimNewlines bool) string {
|
||||
data, err := ioutil.ReadFile("../crypto/testdata/" + name)
|
||||
data, err := ioutil.ReadFile("../crypto/testdata/" + name) //nolint
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
@ -19,4 +21,8 @@ func readTestFile(name string, trimNewlines bool) string {
|
|||
}
|
||||
|
||||
// Corresponding key in ../crypto/testdata/keyring_privateKey
|
||||
const testMailboxPassword = "apple"
|
||||
var testMailboxPassword = []byte("apple")
|
||||
|
||||
func init() {
|
||||
crypto.UpdateTime(testTime) // 2019-05-13T13:37:07+00:00
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,30 +3,40 @@ package helper
|
|||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/internal"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/internal"
|
||||
)
|
||||
|
||||
// SignCleartextMessageArmored signs text given a private key and its passphrase, canonicalizes and trims the newlines,
|
||||
// and returns the PGP-compliant special armoring
|
||||
func SignCleartextMessageArmored(privateKey, passphrase, text string) (string, error) {
|
||||
signingKeyRing, err := crypto.BuildKeyRingArmored(privateKey)
|
||||
func SignCleartextMessageArmored(privateKey string, passphrase []byte, text string) (string, error) {
|
||||
signingKey, err := crypto.NewKeyFromArmored(privateKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = signingKeyRing.UnlockWithPassphrase(passphrase)
|
||||
unlockedKey, err := signingKey.Unlock(passphrase)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return SignCleartextMessage(signingKeyRing, text)
|
||||
keyRing, err := crypto.NewKeyRing(unlockedKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return SignCleartextMessage(keyRing, text)
|
||||
}
|
||||
|
||||
// VerifyCleartextMessageArmored verifies PGP-compliant armored signed plain text given the public key
|
||||
// and returns the text or err if the verification fails
|
||||
func VerifyCleartextMessageArmored(publicKey, armored string, verifyTime int64) (string, error) {
|
||||
verifyKeyRing, err := crypto.BuildKeyRingArmored(publicKey)
|
||||
signingKey, err := crypto.NewKeyFromArmored(publicKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
verifyKeyRing, err := crypto.NewKeyRing(signingKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ import (
|
|||
"regexp"
|
||||
"testing"
|
||||
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/ProtonMail/gopenpgp/crypto"
|
||||
)
|
||||
|
||||
const signedPlainText = "Signed message\n"
|
||||
const testTime = 1557754627 // 2019-05-13T13:37:07+00:00
|
||||
|
||||
var signedMessageTest = regexp.MustCompile(
|
||||
"(?s)^-----BEGIN PGP SIGNED MESSAGE-----.*-----BEGIN PGP SIGNATURE-----.*-----END PGP SIGNATURE-----$")
|
||||
|
||||
|
|
|
|||
119
helper/helper.go
119
helper/helper.go
|
|
@ -1,29 +1,19 @@
|
|||
// helper contains several functions with a simple interface to extend usability and compatibility with gomobile
|
||||
package helper
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ProtonMail/gopenpgp/constants"
|
||||
"github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
)
|
||||
|
||||
// EncryptMessageWithToken encrypts a string with a passphrase using AES256
|
||||
func EncryptMessageWithToken(
|
||||
passphrase, plaintext string,
|
||||
) (ciphertext string, err error) {
|
||||
return EncryptMessageWithTokenAlgo(passphrase, plaintext, constants.AES256)
|
||||
}
|
||||
|
||||
// EncryptMessageWithTokenAlgo encrypts a string with a random token and an algorithm chosen from constants.*
|
||||
func EncryptMessageWithTokenAlgo(
|
||||
token, plaintext, algo string,
|
||||
) (ciphertext string, err error) {
|
||||
// EncryptMessageWithPassword encrypts a string with a passphrase using AES256
|
||||
func EncryptMessageWithPassword(password []byte, plaintext string) (ciphertext string, err error) {
|
||||
var pgpMessage *crypto.PGPMessage
|
||||
|
||||
var message = crypto.NewPlainMessageFromString(plaintext)
|
||||
var key = crypto.NewSymmetricKeyFromToken(token, algo)
|
||||
|
||||
if pgpMessage, err = key.Encrypt(message); err != nil {
|
||||
if pgpMessage, err = crypto.EncryptMessageWithPassword(message, password); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
|
@ -34,19 +24,17 @@ func EncryptMessageWithTokenAlgo(
|
|||
return ciphertext, nil
|
||||
}
|
||||
|
||||
// DecryptMessageWithToken decrypts an armored message with a random token.
|
||||
// DecryptMessageWithPassword decrypts an armored message with a random token.
|
||||
// The algorithm is derived from the armoring.
|
||||
func DecryptMessageWithToken(token, ciphertext string) (plaintext string, err error) {
|
||||
func DecryptMessageWithPassword(password []byte, ciphertext string) (plaintext string, err error) {
|
||||
var message *crypto.PlainMessage
|
||||
var pgpMessage *crypto.PGPMessage
|
||||
|
||||
var key = crypto.NewSymmetricKeyFromToken(token, "")
|
||||
|
||||
if pgpMessage, err = crypto.NewPGPMessageFromArmored(ciphertext); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if message, err = key.Decrypt(pgpMessage); err != nil {
|
||||
if message, err = crypto.DecryptMessageWithPassword(pgpMessage, password); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
|
@ -54,13 +42,18 @@ func DecryptMessageWithToken(token, ciphertext string) (plaintext string, err er
|
|||
}
|
||||
|
||||
// EncryptMessageArmored generates an armored PGP message given a plaintext and an armored public key
|
||||
func EncryptMessageArmored(publicKey, plaintext string) (ciphertext string, err error) {
|
||||
func EncryptMessageArmored(key, plaintext string) (ciphertext string, err error) {
|
||||
var publicKey *crypto.Key
|
||||
var publicKeyRing *crypto.KeyRing
|
||||
var pgpMessage *crypto.PGPMessage
|
||||
|
||||
var message = crypto.NewPlainMessageFromString(plaintext)
|
||||
|
||||
if publicKeyRing, err = crypto.BuildKeyRingArmored(publicKey); err != nil {
|
||||
if publicKey, err = crypto.NewKeyFromArmored(key); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if publicKeyRing, err = crypto.NewKeyRing(publicKey); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
|
@ -78,22 +71,31 @@ func EncryptMessageArmored(publicKey, plaintext string) (ciphertext string, err
|
|||
// EncryptSignMessageArmored generates an armored signed PGP message given a plaintext and an armored public key
|
||||
// a private key and its passphrase
|
||||
func EncryptSignMessageArmored(
|
||||
publicKey, privateKey, passphrase, plaintext string,
|
||||
publicKey, privateKey string, passphrase []byte, plaintext string,
|
||||
) (ciphertext string, err error) {
|
||||
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key
|
||||
var publicKeyRing, privateKeyRing *crypto.KeyRing
|
||||
var pgpMessage *crypto.PGPMessage
|
||||
|
||||
var message = crypto.NewPlainMessageFromString(plaintext)
|
||||
|
||||
if publicKeyRing, err = crypto.BuildKeyRingArmored(publicKey); err != nil {
|
||||
if publicKeyObj, err = crypto.NewKeyFromArmored(publicKey); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if privateKeyRing, err = crypto.BuildKeyRingArmored(privateKey); err != nil {
|
||||
if publicKeyRing, err = crypto.NewKeyRing(publicKeyObj); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = privateKeyRing.UnlockWithPassphrase(passphrase); err != nil {
|
||||
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
|
@ -110,17 +112,22 @@ func EncryptSignMessageArmored(
|
|||
|
||||
// DecryptMessageArmored decrypts an armored PGP message given a private key and its passphrase
|
||||
func DecryptMessageArmored(
|
||||
privateKey, passphrase, ciphertext string,
|
||||
privateKey string, passphrase []byte, ciphertext string,
|
||||
) (plaintext string, err error) {
|
||||
var privateKeyObj, privateKeyUnlocked *crypto.Key
|
||||
var privateKeyRing *crypto.KeyRing
|
||||
var pgpMessage *crypto.PGPMessage
|
||||
var message *crypto.PlainMessage
|
||||
|
||||
if privateKeyRing, err = crypto.BuildKeyRingArmored(privateKey); err != nil {
|
||||
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = privateKeyRing.UnlockWithPassphrase(passphrase); err != nil {
|
||||
if privateKeyUnlocked, err = privateKeyObj.Unlock(passphrase); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if privateKeyRing, err = crypto.NewKeyRing(privateKeyUnlocked); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
|
@ -139,21 +146,30 @@ func DecryptMessageArmored(
|
|||
// and verifies the embedded signature.
|
||||
// Returns the plain data or an error on signature verification failure.
|
||||
func DecryptVerifyMessageArmored(
|
||||
publicKey, privateKey, passphrase, ciphertext string,
|
||||
publicKey, privateKey string, passphrase []byte, ciphertext string,
|
||||
) (plaintext string, err error) {
|
||||
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key
|
||||
var publicKeyRing, privateKeyRing *crypto.KeyRing
|
||||
var pgpMessage *crypto.PGPMessage
|
||||
var message *crypto.PlainMessage
|
||||
|
||||
if publicKeyRing, err = crypto.BuildKeyRingArmored(publicKey); err != nil {
|
||||
if publicKeyObj, err = crypto.NewKeyFromArmored(publicKey); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if privateKeyRing, err = crypto.BuildKeyRingArmored(privateKey); err != nil {
|
||||
if publicKeyRing, err = crypto.NewKeyRing(publicKeyObj); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = privateKeyRing.UnlockWithPassphrase(passphrase); err != nil {
|
||||
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
|
|
@ -172,24 +188,32 @@ func DecryptVerifyMessageArmored(
|
|||
// and its passphrase, the filename, and the unencrypted file data.
|
||||
// Returns keypacket, dataPacket and unarmored (!) signature separate.
|
||||
func EncryptSignAttachment(
|
||||
publicKey, privateKey, passphrase, fileName string,
|
||||
plainData []byte,
|
||||
publicKey, privateKey string, passphrase []byte, fileName string, plainData []byte,
|
||||
) (keyPacket, dataPacket, signature []byte, err error) {
|
||||
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key
|
||||
var publicKeyRing, privateKeyRing *crypto.KeyRing
|
||||
var packets *crypto.PGPSplitMessage
|
||||
var signatureObj *crypto.PGPSignature
|
||||
|
||||
var binMessage = crypto.NewPlainMessage(plainData)
|
||||
|
||||
if publicKeyRing, err = crypto.BuildKeyRingArmored(publicKey); err != nil {
|
||||
if publicKeyObj, err = crypto.NewKeyFromArmored(publicKey); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
if privateKeyRing, err = crypto.BuildKeyRingArmored(privateKey); err != nil {
|
||||
if publicKeyRing, err = crypto.NewKeyRing(publicKeyObj); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
if err = privateKeyRing.UnlockWithPassphrase(passphrase); err != nil {
|
||||
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
|
|
@ -208,25 +232,34 @@ func EncryptSignAttachment(
|
|||
// and an armored (!) signature, given a publicKey, and a privateKey with its passphrase.
|
||||
// Returns the plain data or an error on signature verification failure.
|
||||
func DecryptVerifyAttachment(
|
||||
publicKey, privateKey, passphrase string,
|
||||
keyPacket, dataPacket []byte,
|
||||
publicKey, privateKey string,
|
||||
passphrase, keyPacket, dataPacket []byte,
|
||||
armoredSignature string,
|
||||
) (plainData []byte, err error) {
|
||||
var publicKeyObj, privateKeyObj, unlockedKeyObj *crypto.Key
|
||||
var publicKeyRing, privateKeyRing *crypto.KeyRing
|
||||
var detachedSignature *crypto.PGPSignature
|
||||
var message *crypto.PlainMessage
|
||||
|
||||
var packets = crypto.NewPGPSplitMessage(keyPacket, dataPacket)
|
||||
|
||||
if publicKeyRing, err = crypto.BuildKeyRingArmored(publicKey); err != nil {
|
||||
if publicKeyObj, err = crypto.NewKeyFromArmored(publicKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if privateKeyRing, err = crypto.BuildKeyRingArmored(privateKey); err != nil {
|
||||
if publicKeyRing, err = crypto.NewKeyRing(publicKeyObj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = privateKeyRing.UnlockWithPassphrase(passphrase); err != nil {
|
||||
if privateKeyObj, err = crypto.NewKeyFromArmored(privateKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if unlockedKeyObj, err = privateKeyObj.Unlock(passphrase); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if privateKeyRing, err = crypto.NewKeyRing(unlockedKeyObj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,23 +3,23 @@ package helper
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAESEncryption(t *testing.T) {
|
||||
var plaintext = "Symmetric secret"
|
||||
var passphrase = "passphrase"
|
||||
var passphrase = []byte("passphrase")
|
||||
|
||||
ciphertext, err := EncryptMessageWithToken(passphrase, plaintext)
|
||||
ciphertext, err := EncryptMessageWithPassword(passphrase, plaintext)
|
||||
if err != nil {
|
||||
t.Fatal("Expected no error when encrypting, got:", err)
|
||||
}
|
||||
|
||||
_, err = DecryptMessageWithToken("Wrong passphrase", ciphertext)
|
||||
_, err = DecryptMessageWithPassword([]byte("Wrong passphrase"), ciphertext)
|
||||
assert.EqualError(t, err, "gopenpgp: wrong password in symmetric decryption")
|
||||
|
||||
decrypted, err := DecryptMessageWithToken(passphrase, ciphertext)
|
||||
decrypted, err := DecryptMessageWithPassword(passphrase, ciphertext)
|
||||
if err != nil {
|
||||
t.Fatal("Expected no error when decrypting, got:", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
package helper
|
||||
|
||||
import (
|
||||
"github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
)
|
||||
|
||||
// ExplicitVerifyMessage contains explicitly the signature verification error, for gomobile users
|
||||
type ExplicitVerifyMessage struct {
|
||||
Message *crypto.PlainMessage
|
||||
Message *crypto.PlainMessage
|
||||
SignatureVerificationError *crypto.SignatureVerificationError
|
||||
}
|
||||
|
||||
// DecryptVerifyMessageArmored decrypts an armored PGP message given a private key and its passphrase
|
||||
// DecryptExplicitVerify decrypts an armored PGP message given a private key and its passphrase
|
||||
// and verifies the embedded signature.
|
||||
// Returns the plain data or an error on signature verification failure.
|
||||
func DecryptExplicitVerify(
|
||||
|
|
@ -19,7 +20,7 @@ func DecryptExplicitVerify(
|
|||
) (*ExplicitVerifyMessage, error) {
|
||||
var explicitVerify *ExplicitVerifyMessage
|
||||
|
||||
message, err := privateKeyRing.Decrypt(pgpMessage, publicKeyRing, verifyTime);
|
||||
message, err := privateKeyRing.Decrypt(pgpMessage, publicKeyRing, verifyTime)
|
||||
|
||||
if err != nil {
|
||||
castedErr, isType := err.(crypto.SignatureVerificationError)
|
||||
|
|
@ -28,12 +29,12 @@ func DecryptExplicitVerify(
|
|||
}
|
||||
|
||||
explicitVerify = &ExplicitVerifyMessage{
|
||||
Message: message,
|
||||
Message: message,
|
||||
SignatureVerificationError: &castedErr,
|
||||
}
|
||||
} else {
|
||||
explicitVerify = &ExplicitVerifyMessage{
|
||||
Message: message,
|
||||
Message: message,
|
||||
SignatureVerificationError: nil,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,20 +3,22 @@ package helper
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ProtonMail/gopenpgp/constants"
|
||||
"github.com/ProtonMail/gopenpgp/crypto"
|
||||
"github.com/ProtonMail/gopenpgp/v2/constants"
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestIOSSignedMessageDecryption(t *testing.T) {
|
||||
testPrivateKeyRing, _ := crypto.BuildKeyRingArmored(readTestFile("keyring_privateKey", false))
|
||||
testPublicKeyRing, _ := crypto.BuildKeyRingArmored(readTestFile("mime_publicKey", false))
|
||||
|
||||
privateKey, _ := crypto.NewKeyFromArmored(readTestFile("keyring_privateKey", false))
|
||||
// Password defined in base_test
|
||||
err := testPrivateKeyRing.UnlockWithPassphrase(testMailboxPassword)
|
||||
privateKey, err := privateKey.Unlock(testMailboxPassword)
|
||||
if err != nil {
|
||||
t.Fatal("Expected no error unlocking privateKey, got:", err)
|
||||
}
|
||||
testPrivateKeyRing, _ := crypto.NewKeyRing(privateKey)
|
||||
|
||||
publicKey, _ := crypto.NewKeyFromArmored(readTestFile("mime_publicKey", false))
|
||||
testPublicKeyRing, _ := crypto.NewKeyRing(publicKey)
|
||||
|
||||
pgpMessage, err := crypto.NewPGPMessageFromArmored(readTestFile("message_signed", false))
|
||||
if err != nil {
|
||||
|
|
@ -31,7 +33,8 @@ func TestIOSSignedMessageDecryption(t *testing.T) {
|
|||
assert.Exactly(t, constants.SIGNATURE_NO_VERIFIER, decrypted.SignatureVerificationError.Status)
|
||||
assert.Exactly(t, readTestFile("message_plaintext", true), decrypted.Message.GetString())
|
||||
|
||||
testPublicKeyRing, _ = crypto.BuildKeyRingArmored(readTestFile("keyring_publicKey", false))
|
||||
publicKey, _ = crypto.NewKeyFromArmored(readTestFile("keyring_publicKey", false))
|
||||
testPublicKeyRing, _ = crypto.NewKeyRing(publicKey)
|
||||
|
||||
pgpMessage, err = testPublicKeyRing.Encrypt(decrypted.Message, testPrivateKeyRing)
|
||||
if err != nil {
|
||||
|
|
|
|||
48
helper/key.go
Normal file
48
helper/key.go
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
package helper
|
||||
|
||||
import (
|
||||
"github.com/ProtonMail/gopenpgp/v2/crypto"
|
||||
)
|
||||
|
||||
// UpdatePrivateKeyPassphrase decrypts the given armored privateKey with oldPassphrase,
|
||||
// re-encrypts it with newPassphrase, and returns the new armored key.
|
||||
func UpdatePrivateKeyPassphrase(
|
||||
privateKey string,
|
||||
oldPassphrase, newPassphrase []byte,
|
||||
) (string, error) {
|
||||
key, err := crypto.NewKeyFromArmored(privateKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
unlocked, err := key.Unlock(oldPassphrase)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
locked, err := unlocked.Lock(newPassphrase)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
unlocked.ClearPrivateParams()
|
||||
return locked.Armor()
|
||||
}
|
||||
|
||||
// GenerateKey generates a key of the given keyType ("rsa" or "x25519"), encrypts it, and returns an armored string.
|
||||
// If keyType is "rsa", bits is the RSA bitsize of the key.
|
||||
// If keyType is "x25519" bits is unused.
|
||||
func GenerateKey(name, email string, passphrase []byte, keyType string, bits int) (string, error) {
|
||||
key, err := crypto.GenerateKey(name, email, keyType, bits)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
locked, err := key.Lock(passphrase)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
key.ClearPrivateParams()
|
||||
return locked.Armor()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue