package helper import ( "strings" "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 string, passphrase []byte, text string) (string, error) { signingKey, err := crypto.NewKeyFromArmored(privateKey) if err != nil { return "", err } unlockedKey, err := signingKey.Unlock(passphrase) if err != nil { return "", err } defer unlockedKey.ClearPrivateParams() 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) { signingKey, err := crypto.NewKeyFromArmored(publicKey) if err != nil { return "", err } verifyKeyRing, err := crypto.NewKeyRing(signingKey) if err != nil { return "", err } return VerifyCleartextMessage(verifyKeyRing, armored, verifyTime) } // SignCleartextMessage signs text given a private keyring, canonicalizes and // trims the newlines, and returns the PGP-compliant special armoring. func SignCleartextMessage(keyRing *crypto.KeyRing, text string) (string, error) { text = canonicalizeAndTrim(text) message := crypto.NewPlainMessageFromString(text) signature, err := keyRing.SignDetached(message) if err != nil { return "", err } return crypto.NewClearTextMessage(message.GetBinary(), signature.GetBinary()).GetArmored() } // VerifyCleartextMessage verifies PGP-compliant armored signed plain text // given the public keyring and returns the text or err if the verification // fails. func VerifyCleartextMessage(keyRing *crypto.KeyRing, armored string, verifyTime int64) (string, error) { clearTextMessage, err := crypto.NewClearTextMessageFromArmored(armored) if err != nil { return "", err } message := crypto.NewPlainMessageFromString(clearTextMessage.GetString()) signature := crypto.NewPGPSignature(clearTextMessage.GetBinarySignature()) err = keyRing.VerifyDetached(message, signature, verifyTime) if err != nil { return "", err } return message.GetString(), nil } // ----- INTERNAL FUNCTIONS ----- // canonicalizeAndTrim alters a string canonicalizing and trimming the newlines. func canonicalizeAndTrim(text string) string { text = internal.TrimNewlines(text) text = strings.ReplaceAll(strings.ReplaceAll(text, "\r\n", "\n"), "\n", "\r\n") return text }