Update lint (#44)

* Reduce complexity of SignatureCollector.Accept

* Add stylecheck linter, and lint accordingly

* Rephrase some comments

* godot - Top level comments should end with a dot.

* nestif - Reduce nested complexity of code

* Review changes

Co-authored-by: Aron Wussler <aron@wussler.it>
This commit is contained in:
zugzwang 2020-04-28 13:55:36 +02:00 committed by GitHub
parent 222decb919
commit ac8a49c114
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 252 additions and 265 deletions

View file

@ -11,44 +11,17 @@ issues:
exclude-use-default: false exclude-use-default: false
exclude: exclude:
- Using the variable on range scope `tt` in function literal - Using the variable on range scope `tt` in function literal
- GetJsonSHA256Fingerprints should be GetJSONSHA256Fingerprints
- ST1003 # CamelCase variables; see constants/cipher.go
linters: linters:
enable: enable-all: true
- deadcode # Finds unused code [fast: true, auto-fix: false]
- errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases [fast: true, auto-fix: false]
- gosimple # Linter for Go source code that specializes in simplifying a code [fast: true, auto-fix: false]
- govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string [fast: true, auto-fix: false]
- ineffassign # Detects when assignments to existing variables are not used [fast: true, auto-fix: false]
- staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks [fast: true, auto-fix: false]
- structcheck # Finds unused struct fields [fast: true, auto-fix: false]
- typecheck # Like the front-end of a Go compiler, parses and type-checks Go code [fast: true, auto-fix: false]
- unused # Checks Go code for unused constants, variables, functions and types [fast: false, auto-fix: false]
- varcheck # Finds unused global variables and constants [fast: true, auto-fix: false]
- depguard # Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false]
- dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false]
# - dupl # Tool for code clone detection [fast: true, auto-fix: false]
- funlen # Tool for detection of long functions [fast: true, auto-fix: false]
# - gochecknoglobals # Checks that no globals are present in Go code [fast: true, auto-fix: false]
# - gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false]
- goconst # Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false]
- gocritic # The most opinionated Go source code linter [fast: true, auto-fix: false]
- gocyclo # Computes and checks the cyclomatic complexity of functions [fast: true, auto-fix: false]
- godox # Tool for detection of FIXME, TODO and other comment keywords [fast: true, auto-fix: false]
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification [fast: true, auto-fix: true]
- goimports # Goimports does everything that gofmt does. Additionally it checks unused imports [fast: true, auto-fix: true]
# - golint # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes [fast: true, auto-fix: false]
- gosec # Inspects source code for security problems [fast: true, auto-fix: false]
- interfacer # Linter that suggests narrower interface types [fast: true, auto-fix: false]
- maligned # Tool to detect Go structs that would take less memory if their fields were sorted [fast: true, auto-fix: false]
- misspell # Finds commonly misspelled English words in comments [fast: true, auto-fix: true]
- nakedret # Finds naked returns in functions greater than a specified function length [fast: true, auto-fix: false]
- prealloc # Finds slice declarations that could potentially be preallocated [fast: true, auto-fix: false]
- scopelint # Scopelint checks for unpinned variables in go programs [fast: true, auto-fix: false]
# - stylecheck # Stylecheck is a replacement for golint [fast: true, auto-fix: false]
- unconvert # Remove unnecessary type conversions [fast: true, auto-fix: false]
- unparam # Reports unused function parameters [fast: true, auto-fix: false]
- whitespace # Tool for detection of leading and trailing whitespace [fast: true, auto-fix: true]
disable: disable:
- dupl # Tool for code clone detection [fast: true, auto-fix: false]
- gochecknoglobals # Checks that no globals are present in Go code [fast: true, auto-fix: false]
- gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false]
- golint # Golint differs from gofmt. Gofmt reformats Go source code, whereas golint prints out style mistakes [fast: true, auto-fix: false]
- gomnd # An analyzer to detect magic numbers. [fast: true, auto-fix: false]
- lll # Reports long lines [fast: true, auto-fix: false]
- testpackage # Makes you use a separate _test package [fast: true, auto-fix: false]
- wsl # Whitespace Linter - Forces you to use empty lines! [fast: true, auto-fix: false] - wsl # Whitespace Linter - Forces you to use empty lines! [fast: true, auto-fix: false]
- lll # Reports long lines [fast: true, auto-fix: false]\

View file

@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Changed ## Changed
- Providing empty passphrase does no longer throw an error when unlocking an unencrypted private key - Providing empty passphrase does no longer throw an error when unlocking an unencrypted private key
- Improved code linter
### Added ### Added
- SHA256 fingerprint support - SHA256 fingerprint support

View file

@ -22,14 +22,14 @@ type AttachmentProcessor struct {
err error err error
} }
// Process writes attachment data to be encrypted // Process writes attachment data to be encrypted.
func (ap *AttachmentProcessor) Process(plainData []byte) { func (ap *AttachmentProcessor) Process(plainData []byte) {
if _, err := (*ap.w).Write(plainData); err != nil { if _, err := (*ap.w).Write(plainData); err != nil {
panic(err) panic(err)
} }
} }
// Finish closes the attachment and returns the encrypted data // Finish closes the attachment and returns the encrypted data.
func (ap *AttachmentProcessor) Finish() (*PGPSplitMessage, error) { func (ap *AttachmentProcessor) Finish() (*PGPSplitMessage, error) {
if ap.err != nil { if ap.err != nil {
return nil, ap.err return nil, ap.err

View file

@ -20,7 +20,7 @@ import (
packet "golang.org/x/crypto/openpgp/packet" packet "golang.org/x/crypto/openpgp/packet"
) )
// Key contains a single private or public key // Key contains a single private or public key.
type Key struct { type Key struct {
// PGP entities in this keyring. // PGP entities in this keyring.
entity *openpgp.Entity entity *openpgp.Entity
@ -50,12 +50,12 @@ func NewKeyFromReader(r io.Reader) (key *Key, err error) {
return key, nil return key, nil
} }
// NewKey creates a new key from the first key in the unarmored binary data // NewKey creates a new key from the first key in the unarmored binary data.
func NewKey(binKeys []byte) (key *Key, err error) { func NewKey(binKeys []byte) (key *Key, err error) {
return NewKeyFromReader(bytes.NewReader(clone(binKeys))) return NewKeyFromReader(bytes.NewReader(clone(binKeys)))
} }
// NewKeyFromArmored creates a new key from the first key in an armored // NewKeyFromArmored creates a new key from the first key in an armored string.
func NewKeyFromArmored(armored string) (key *Key, err error) { func NewKeyFromArmored(armored string) (key *Key, err error) {
return NewKeyFromArmoredReader(strings.NewReader(armored)) return NewKeyFromArmoredReader(strings.NewReader(armored))
} }
@ -132,7 +132,7 @@ func (key *Key) Lock(passphrase []byte) (*Key, error) {
return lockedKey, nil return lockedKey, nil
} }
// Unlock unlocks a copy of the key // Unlock unlocks a copy of the key.
func (key *Key) Unlock(passphrase []byte) (*Key, error) { func (key *Key) Unlock(passphrase []byte) (*Key, error) {
isLocked, err := key.IsLocked() isLocked, err := key.IsLocked()
if err != nil { if err != nil {
@ -234,12 +234,12 @@ func (key *Key) IsExpired() bool {
return !ok return !ok
} }
// IsPrivate returns true if the key is private // IsPrivate returns true if the key is private.
func (key *Key) IsPrivate() bool { func (key *Key) IsPrivate() bool {
return key.entity.PrivateKey != nil return key.entity.PrivateKey != nil
} }
// IsLocked checks if a private key is locked // IsLocked checks if a private key is locked.
func (key *Key) IsLocked() (bool, error) { func (key *Key) IsLocked() (bool, error) {
if key.entity.PrivateKey == nil { if key.entity.PrivateKey == nil {
return true, errors.New("gopenpgp: a public key cannot be locked") return true, errors.New("gopenpgp: a public key cannot be locked")
@ -254,7 +254,7 @@ func (key *Key) IsLocked() (bool, error) {
return key.entity.PrivateKey.Encrypted, nil return key.entity.PrivateKey.Encrypted, nil
} }
// IsUnlocked checks if a private key is unlocked // IsUnlocked checks if a private key is unlocked.
func (key *Key) IsUnlocked() (bool, error) { func (key *Key) IsUnlocked() (bool, error) {
if key.entity.PrivateKey == nil { if key.entity.PrivateKey == nil {
return true, errors.New("gopenpgp: a public key cannot be unlocked") return true, errors.New("gopenpgp: a public key cannot be unlocked")
@ -269,7 +269,8 @@ func (key *Key) IsUnlocked() (bool, error) {
return !key.entity.PrivateKey.Encrypted, nil return !key.entity.PrivateKey.Encrypted, nil
} }
// Check verifies if the public keys match the private key parameters by signing and verifying // Check verifies if the public keys match the private key parameters by
// signing and verifying.
func (key *Key) Check() (bool, error) { func (key *Key) Check() (bool, error) {
var err error var err error
testSign := bytes.Repeat([]byte{0x01}, 64) testSign := bytes.Repeat([]byte{0x01}, 64)
@ -314,22 +315,22 @@ func (key *Key) PrintFingerprints() {
fmt.Println("PrimaryKey:" + hex.EncodeToString(key.entity.PrimaryKey.Fingerprint[:])) fmt.Println("PrimaryKey:" + hex.EncodeToString(key.entity.PrimaryKey.Fingerprint[:]))
} }
// GetHexKeyID returns the key ID, hex encoded as a string // GetHexKeyID returns the key ID, hex encoded as a string.
func (key *Key) GetHexKeyID() string { func (key *Key) GetHexKeyID() string {
return strconv.FormatUint(key.GetKeyID(), 16) return strconv.FormatUint(key.GetKeyID(), 16)
} }
// GetKeyID returns the key ID, encoded as 8-byte int // GetKeyID returns the key ID, encoded as 8-byte int.
func (key *Key) GetKeyID() uint64 { func (key *Key) GetKeyID() uint64 {
return key.entity.PrimaryKey.KeyId return key.entity.PrimaryKey.KeyId
} }
// GetFingerprint gets the fingerprint from the key // GetFingerprint gets the fingerprint from the key.
func (key *Key) GetFingerprint() string { func (key *Key) GetFingerprint() string {
return hex.EncodeToString(key.entity.PrimaryKey.Fingerprint[:]) return hex.EncodeToString(key.entity.PrimaryKey.Fingerprint[:])
} }
// GetSHA256Fingerprints computes the SHA256 fingerprints of the key and subkeys // GetSHA256Fingerprints computes the SHA256 fingerprints of the key and subkeys.
func (key *Key) GetSHA256Fingerprints() (fingerprints []string) { func (key *Key) GetSHA256Fingerprints() (fingerprints []string) {
fingerprints = append(fingerprints, hex.EncodeToString(getSHA256FingerprintBytes(key.entity.PrimaryKey))) fingerprints = append(fingerprints, hex.EncodeToString(getSHA256FingerprintBytes(key.entity.PrimaryKey)))
for _, sub := range key.entity.Subkeys { for _, sub := range key.entity.Subkeys {
@ -340,7 +341,8 @@ func (key *Key) GetSHA256Fingerprints() (fingerprints []string) {
// --- Internal methods // --- Internal methods
// getSHA256FingerprintBytes computes the SHA256 fingerprint of a public key object // getSHA256FingerprintBytes computes the SHA256 fingerprint of a public key
// object.
func getSHA256FingerprintBytes(pk *packet.PublicKey) []byte { func getSHA256FingerprintBytes(pk *packet.PublicKey) []byte {
fingerPrint := sha256.New() fingerPrint := sha256.New()

View file

@ -26,7 +26,7 @@ type Identity struct {
// --- New keyrings // --- New keyrings
// NewKeyRing creates a new KeyRing, empty if key is nil // NewKeyRing creates a new KeyRing, empty if key is nil.
func NewKeyRing(key *Key) (*KeyRing, error) { func NewKeyRing(key *Key) (*KeyRing, error) {
keyRing := &KeyRing{} keyRing := &KeyRing{}
var err error var err error
@ -36,7 +36,7 @@ func NewKeyRing(key *Key) (*KeyRing, error) {
return keyRing, err return keyRing, err
} }
// --- Add keys to keyring // AddKey adds the given key to the keyring.
func (keyRing *KeyRing) AddKey(key *Key) error { func (keyRing *KeyRing) AddKey(key *Key) error {
if key.IsPrivate() { if key.IsPrivate() {
unlocked, err := key.IsUnlocked() unlocked, err := key.IsUnlocked()
@ -91,17 +91,17 @@ func (keyRing *KeyRing) getSigningEntity() (*openpgp.Entity, error) {
// --- Extract info from key // --- Extract info from key
// CountEntities returns the number of entities in the keyring // CountEntities returns the number of entities in the keyring.
func (keyRing *KeyRing) CountEntities() int { func (keyRing *KeyRing) CountEntities() int {
return len(keyRing.entities) return len(keyRing.entities)
} }
// CountDecryptionEntities returns the number of entities in the keyring // CountDecryptionEntities returns the number of entities in the keyring.
func (keyRing *KeyRing) CountDecryptionEntities() int { func (keyRing *KeyRing) CountDecryptionEntities() int {
return len(keyRing.entities.DecryptionKeys()) return len(keyRing.entities.DecryptionKeys())
} }
// Identities returns the list of identities associated with this key ring. // GetIdentities returns the list of identities associated with this key ring.
func (keyRing *KeyRing) GetIdentities() []*Identity { func (keyRing *KeyRing) GetIdentities() []*Identity {
var identities []*Identity var identities []*Identity
for _, e := range keyRing.entities { for _, e := range keyRing.entities {
@ -172,7 +172,7 @@ func FilterExpiredKeys(contactKeys []*KeyRing) (filteredKeys []*KeyRing, err err
return filteredKeys, nil return filteredKeys, nil
} }
// FirstKey returns a KeyRing with only the first key of the original one // FirstKey returns a KeyRing with only the first key of the original one.
func (keyRing *KeyRing) FirstKey() (*KeyRing, error) { func (keyRing *KeyRing) FirstKey() (*KeyRing, error) {
if len(keyRing.entities) == 0 { if len(keyRing.entities) == 0 {
return nil, errors.New("gopenpgp: No key available in this keyring") return nil, errors.New("gopenpgp: No key available in this keyring")
@ -183,7 +183,7 @@ func (keyRing *KeyRing) FirstKey() (*KeyRing, error) {
return newKeyRing.Copy() return newKeyRing.Copy()
} }
// Copy creates a deep copy of the keyring // Copy creates a deep copy of the keyring.
func (keyRing *KeyRing) Copy() (*KeyRing, error) { func (keyRing *KeyRing) Copy() (*KeyRing, error) {
newKeyRing := &KeyRing{} newKeyRing := &KeyRing{}
@ -223,7 +223,7 @@ func (keyRing *KeyRing) ClearPrivateParams() {
// INTERNAL FUNCTIONS // INTERNAL FUNCTIONS
// append appends a key to the keyring // appendKey appends a key to the keyring.
func (keyRing *KeyRing) appendKey(key *Key) { func (keyRing *KeyRing) appendKey(key *Key) {
keyRing.entities = append(keyRing.entities, key.entity) keyRing.entities = append(keyRing.entities, key.entity)
} }

View file

@ -12,8 +12,8 @@ import (
// Encrypt encrypts a PlainMessage, outputs a PGPMessage. // Encrypt encrypts a PlainMessage, outputs a PGPMessage.
// If an unlocked private key is also provided it will also sign the message. // If an unlocked private key is also provided it will also sign the message.
// * message : The plaintext input as a PlainMessage // * message : The plaintext input as a PlainMessage.
// * privateKey : (optional) an unlocked private keyring to include signature in the message // * privateKey : (optional) an unlocked private keyring to include signature in the message.
func (keyRing *KeyRing) Encrypt(message *PlainMessage, privateKey *KeyRing) (*PGPMessage, error) { func (keyRing *KeyRing) Encrypt(message *PlainMessage, privateKey *KeyRing) (*PGPMessage, error) {
encrypted, err := asymmetricEncrypt(message.GetBinary(), keyRing, privateKey, message.IsBinary()) encrypted, err := asymmetricEncrypt(message.GetBinary(), keyRing, privateKey, message.IsBinary())
if err != nil { if err != nil {
@ -28,7 +28,8 @@ func (keyRing *KeyRing) Encrypt(message *PlainMessage, privateKey *KeyRing) (*PG
// * verifyKey : Public key for signature verification (optional) // * verifyKey : Public key for signature verification (optional)
// * verifyTime : Time at verification (necessary only if verifyKey is not nil) // * verifyTime : Time at verification (necessary only if verifyKey is not nil)
// //
// When verifyKey is not provided, then verifyTime should be zero, and signature verification will be ignored // When verifyKey is not provided, then verifyTime should be zero, and
// signature verification will be ignored.
func (keyRing *KeyRing) Decrypt( func (keyRing *KeyRing) Decrypt(
message *PGPMessage, verifyKey *KeyRing, verifyTime int64, message *PGPMessage, verifyKey *KeyRing, verifyTime int64,
) (*PlainMessage, error) { ) (*PlainMessage, error) {
@ -37,7 +38,7 @@ func (keyRing *KeyRing) Decrypt(
return NewPlainMessage(decrypted), err return NewPlainMessage(decrypted), err
} }
// SignDetached generates and returns a PGPSignature for a given PlainMessage // SignDetached generates and returns a PGPSignature for a given PlainMessage.
func (keyRing *KeyRing) SignDetached(message *PlainMessage) (*PGPSignature, error) { func (keyRing *KeyRing) SignDetached(message *PlainMessage) (*PGPSignature, error) {
signEntity, err := keyRing.getSigningEntity() signEntity, err := keyRing.getSigningEntity()
if err != nil { if err != nil {
@ -55,7 +56,7 @@ func (keyRing *KeyRing) SignDetached(message *PlainMessage) (*PGPSignature, erro
} }
// VerifyDetached verifies a PlainMessage with embedded a PGPSignature // VerifyDetached verifies a PlainMessage with embedded a PGPSignature
// and returns a SignatureVerificationError if fails // and returns a SignatureVerificationError if fails.
func (keyRing *KeyRing) VerifyDetached(message *PlainMessage, signature *PGPSignature, verifyTime int64) error { func (keyRing *KeyRing) VerifyDetached(message *PlainMessage, signature *PGPSignature, verifyTime int64) error {
return verifySignature( return verifySignature(
keyRing.entities, keyRing.entities,
@ -67,7 +68,7 @@ func (keyRing *KeyRing) VerifyDetached(message *PlainMessage, signature *PGPSign
// ------ INTERNAL FUNCTIONS ------- // ------ INTERNAL FUNCTIONS -------
// Core for encryption+signature functions // Core for encryption+signature functions.
func asymmetricEncrypt(data []byte, publicKey *KeyRing, privateKey *KeyRing, isBinary bool) ([]byte, error) { func asymmetricEncrypt(data []byte, publicKey *KeyRing, privateKey *KeyRing, isBinary bool) ([]byte, error) {
var outBuf bytes.Buffer var outBuf bytes.Buffer
var encryptWriter io.WriteCloser var encryptWriter io.WriteCloser
@ -111,7 +112,7 @@ func asymmetricEncrypt(data []byte, publicKey *KeyRing, privateKey *KeyRing, isB
return outBuf.Bytes(), nil return outBuf.Bytes(), nil
} }
// Core for decryption+verification functions // Core for decryption+verification functions.
func asymmetricDecrypt( func asymmetricDecrypt(
encryptedIO io.Reader, privateKey *KeyRing, verifyKey *KeyRing, verifyTime int64, encryptedIO io.Reader, privateKey *KeyRing, verifyKey *KeyRing, verifyTime int64,
) (plaintext []byte, err error) { ) (plaintext []byte, err error) {

View file

@ -47,8 +47,7 @@ type PGPSplitMessage struct {
KeyPacket []byte KeyPacket []byte
} }
// ClearTextMessage, split signed clear text message container. // A ClearTextMessage is a signed but not encrypted PGP message,
// A Cleartext message is a signed PGP message, that is not encrypted,
// i.e. the ones beginning with -----BEGIN PGP SIGNED MESSAGE----- // i.e. the ones beginning with -----BEGIN PGP SIGNED MESSAGE-----
type ClearTextMessage struct { type ClearTextMessage struct {
Data []byte Data []byte
@ -126,7 +125,8 @@ func NewPGPSignature(data []byte) *PGPSignature {
} }
} }
// NewPGPSignatureFromArmored generates a new PGPSignature from the armored string ready for verification. // NewPGPSignatureFromArmored generates a new PGPSignature from the armored
// string ready for verification.
func NewPGPSignatureFromArmored(armored string) (*PGPSignature, error) { func NewPGPSignatureFromArmored(armored string) (*PGPSignature, error) {
encryptedIO, err := internal.Unarmor(armored) encryptedIO, err := internal.Unarmor(armored)
if err != nil { if err != nil {
@ -143,7 +143,8 @@ func NewPGPSignatureFromArmored(armored string) (*PGPSignature, error) {
}, nil }, nil
} }
// NewClearTextMessage generates a new ClearTextMessage from data and signature // NewClearTextMessage generates a new ClearTextMessage from data and
// signature.
func NewClearTextMessage(data []byte, signature []byte) *ClearTextMessage { func NewClearTextMessage(data []byte, signature []byte) *ClearTextMessage {
return &ClearTextMessage{ return &ClearTextMessage{
Data: clone(data), Data: clone(data),
@ -151,7 +152,8 @@ func NewClearTextMessage(data []byte, signature []byte) *ClearTextMessage {
} }
} }
// NewClearTextMessageFromArmored returns the message body and unarmored signature from a clearsigned message. // NewClearTextMessageFromArmored returns the message body and unarmored
// signature from a clearsigned message.
func NewClearTextMessageFromArmored(signedMessage string) (*ClearTextMessage, error) { func NewClearTextMessageFromArmored(signedMessage string) (*ClearTextMessage, error) {
modulusBlock, rest := clearsign.Decode([]byte(signedMessage)) modulusBlock, rest := clearsign.Decode([]byte(signedMessage))
if len(rest) != 0 { if len(rest) != 0 {
@ -168,79 +170,84 @@ func NewClearTextMessageFromArmored(signedMessage string) (*ClearTextMessage, er
// ---- MODEL METHODS ----- // ---- MODEL METHODS -----
// GetBinary returns the binary content of the message as a []byte // GetBinary returns the binary content of the message as a []byte.
func (msg *PlainMessage) GetBinary() []byte { func (msg *PlainMessage) GetBinary() []byte {
return msg.Data return msg.Data
} }
// GetString returns the content of the message as a string // GetString returns the content of the message as a string.
func (msg *PlainMessage) GetString() string { func (msg *PlainMessage) GetString() string {
return string(msg.Data) return string(msg.Data)
} }
// GetBase64 returns the base-64 encoded binary content of the message as a string // GetBase64 returns the base-64 encoded binary content of the message as a
// string.
func (msg *PlainMessage) GetBase64() string { func (msg *PlainMessage) GetBase64() string {
return base64.StdEncoding.EncodeToString(msg.Data) return base64.StdEncoding.EncodeToString(msg.Data)
} }
// NewReader returns a New io.Reader for the binary data of the message // NewReader returns a New io.Reader for the binary data of the message.
func (msg *PlainMessage) NewReader() io.Reader { func (msg *PlainMessage) NewReader() io.Reader {
return bytes.NewReader(msg.GetBinary()) return bytes.NewReader(msg.GetBinary())
} }
// IsText returns whether the message is a text message // IsText returns whether the message is a text message.
func (msg *PlainMessage) IsText() bool { func (msg *PlainMessage) IsText() bool {
return msg.TextType return msg.TextType
} }
// IsBinary returns whether the message is a binary message // IsBinary returns whether the message is a binary message.
func (msg *PlainMessage) IsBinary() bool { func (msg *PlainMessage) IsBinary() bool {
return !msg.TextType return !msg.TextType
} }
// GetBinary returns the unarmored binary content of the message as a []byte // GetBinary returns the unarmored binary content of the message as a []byte.
func (msg *PGPMessage) GetBinary() []byte { func (msg *PGPMessage) GetBinary() []byte {
return msg.Data return msg.Data
} }
// NewReader returns a New io.Reader for the unarmored binary data of the message // NewReader returns a New io.Reader for the unarmored binary data of the
// message.
func (msg *PGPMessage) NewReader() io.Reader { func (msg *PGPMessage) NewReader() io.Reader {
return bytes.NewReader(msg.GetBinary()) return bytes.NewReader(msg.GetBinary())
} }
// GetArmored returns the armored message as a string // GetArmored returns the armored message as a string.
func (msg *PGPMessage) GetArmored() (string, error) { func (msg *PGPMessage) GetArmored() (string, error) {
return armor.ArmorWithType(msg.Data, constants.PGPMessageHeader) return armor.ArmorWithType(msg.Data, constants.PGPMessageHeader)
} }
// GetBinaryDataPacket returns the unarmored binary datapacket as a []byte // GetBinaryDataPacket returns the unarmored binary datapacket as a []byte.
func (msg *PGPSplitMessage) GetBinaryDataPacket() []byte { func (msg *PGPSplitMessage) GetBinaryDataPacket() []byte {
return msg.DataPacket return msg.DataPacket
} }
// GetBinaryKeyPacket returns the unarmored binary keypacket as a []byte // GetBinaryKeyPacket returns the unarmored binary keypacket as a []byte.
func (msg *PGPSplitMessage) GetBinaryKeyPacket() []byte { func (msg *PGPSplitMessage) GetBinaryKeyPacket() []byte {
return msg.KeyPacket return msg.KeyPacket
} }
// GetBinary returns the unarmored binary joined packets as a []byte // GetBinary returns the unarmored binary joined packets as a []byte.
func (msg *PGPSplitMessage) GetBinary() []byte { func (msg *PGPSplitMessage) GetBinary() []byte {
return append(msg.KeyPacket, msg.DataPacket...) return append(msg.KeyPacket, msg.DataPacket...)
} }
// GetArmored returns the armored message as a string, with joined data and key packets // GetArmored returns the armored message as a string, with joined data and key
// packets.
func (msg *PGPSplitMessage) GetArmored() (string, error) { func (msg *PGPSplitMessage) GetArmored() (string, error) {
return armor.ArmorWithType(msg.GetBinary(), constants.PGPMessageHeader) return armor.ArmorWithType(msg.GetBinary(), constants.PGPMessageHeader)
} }
// GetPGPMessage joins asymmetric session key packet with the symmetric data packet to obtain a PGP message // GetPGPMessage joins asymmetric session key packet with the symmetric data
// packet to obtain a PGP message.
func (msg *PGPSplitMessage) GetPGPMessage() *PGPMessage { func (msg *PGPSplitMessage) GetPGPMessage() *PGPMessage {
return NewPGPMessage(append(msg.KeyPacket, msg.DataPacket...)) return NewPGPMessage(append(msg.KeyPacket, msg.DataPacket...))
} }
// SeparateKeyAndData returns the first keypacket and the (hopefully unique) dataPacket (not verified) // SeparateKeyAndData returns the first keypacket and the (hopefully unique)
// * estimatedLength is the estimate length of the message // dataPacket (not verified).
// * garbageCollector > 0 activates the garbage collector // * estimatedLength is the estimate length of the message.
// * garbageCollector > 0 activates the garbage collector.
func (msg *PGPMessage) SeparateKeyAndData(estimatedLength, garbageCollector int) (outSplit *PGPSplitMessage, err error) { func (msg *PGPMessage) SeparateKeyAndData(estimatedLength, garbageCollector int) (outSplit *PGPSplitMessage, err error) {
// For info on each, see: https://golang.org/pkg/runtime/#MemStats // For info on each, see: https://golang.org/pkg/runtime/#MemStats
packets := packet.NewReader(bytes.NewReader(msg.Data)) packets := packet.NewReader(bytes.NewReader(msg.Data))
@ -334,32 +341,33 @@ func (msg *PGPMessage) SeparateKeyAndData(estimatedLength, garbageCollector int)
return outSplit, nil return outSplit, nil
} }
// GetBinary returns the unarmored binary content of the signature as a []byte // GetBinary returns the unarmored binary content of the signature as a []byte.
func (msg *PGPSignature) GetBinary() []byte { func (msg *PGPSignature) GetBinary() []byte {
return msg.Data return msg.Data
} }
// GetArmored returns the armored signature as a string // GetArmored returns the armored signature as a string.
func (msg *PGPSignature) GetArmored() (string, error) { func (msg *PGPSignature) GetArmored() (string, error) {
return armor.ArmorWithType(msg.Data, constants.PGPSignatureHeader) return armor.ArmorWithType(msg.Data, constants.PGPSignatureHeader)
} }
// GetBinary returns the unarmored signed data as a []byte // GetBinary returns the unarmored signed data as a []byte.
func (msg *ClearTextMessage) GetBinary() []byte { func (msg *ClearTextMessage) GetBinary() []byte {
return msg.Data return msg.Data
} }
// GetString returns the unarmored signed data as a string // GetString returns the unarmored signed data as a string.
func (msg *ClearTextMessage) GetString() string { func (msg *ClearTextMessage) GetString() string {
return string(msg.Data) return string(msg.Data)
} }
// GetBinarySignature returns the unarmored binary signature as a []byte // GetBinarySignature returns the unarmored binary signature as a []byte.
func (msg *ClearTextMessage) GetBinarySignature() []byte { func (msg *ClearTextMessage) GetBinarySignature() []byte {
return msg.Signature return msg.Signature
} }
// GetArmored armors plaintext and signature with the PGP SIGNED MESSAGE armoring // GetArmored armors plaintext and signature with the PGP SIGNED MESSAGE
// armoring.
func (msg *ClearTextMessage) GetArmored() (string, error) { func (msg *ClearTextMessage) GetArmored() (string, error) {
armSignature, err := armor.ArmorWithType(msg.GetBinarySignature(), constants.PGPSignatureHeader) armSignature, err := armor.ArmorWithType(msg.GetBinarySignature(), constants.PGPSignatureHeader)
if err != nil { if err != nil {

View file

@ -10,10 +10,11 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
// Encrypt encrypts a PlainMessage to PGPMessage with a SymmetricKey // EncryptMessageWithPassword encrypts a PlainMessage to PGPMessage with a
// * message : The plain data as a PlainMessage // SymmetricKey.
// * password: A password that will be derived into an encryption key // * message : The plain data as a PlainMessage.
// * output : The encrypted data as PGPMessage // * password: A password that will be derived into an encryption key.
// * output : The encrypted data as PGPMessage.
func EncryptMessageWithPassword(message *PlainMessage, password []byte) (*PGPMessage, error) { func EncryptMessageWithPassword(message *PlainMessage, password []byte) (*PGPMessage, error) {
encrypted, err := passwordEncrypt(message.GetBinary(), password, message.IsBinary()) encrypted, err := passwordEncrypt(message.GetBinary(), password, message.IsBinary())
if err != nil { if err != nil {
@ -23,10 +24,10 @@ func EncryptMessageWithPassword(message *PlainMessage, password []byte) (*PGPMes
return NewPGPMessage(encrypted), nil return NewPGPMessage(encrypted), nil
} }
// Decrypt decrypts password protected pgp binary messages // DecryptMessageWithPassword decrypts password protected pgp binary messages.
// * encrypted: The encrypted data as PGPMessage // * encrypted: The encrypted data as PGPMessage.
// * password: A password that will be derived into an encryption key // * password: A password that will be derived into an encryption key.
// * output: The decrypted data as PlainMessage // * output: The decrypted data as PlainMessage.
func DecryptMessageWithPassword(message *PGPMessage, password []byte) (*PlainMessage, error) { func DecryptMessageWithPassword(message *PGPMessage, password []byte) (*PlainMessage, error) {
decrypted, err := passwordDecrypt(message.NewReader(), password) decrypted, err := passwordDecrypt(message.NewReader(), password)
if err != nil { if err != nil {

View file

@ -45,7 +45,7 @@ func (sk *SessionKey) GetBase64Key() string {
return base64.StdEncoding.EncodeToString(sk.Key) return base64.StdEncoding.EncodeToString(sk.Key)
} }
// RandomToken generates a random token with the specified key size // RandomToken generates a random token with the specified key size.
func RandomToken(size int) ([]byte, error) { func RandomToken(size int) ([]byte, error) {
config := &packet.Config{DefaultCipher: packet.CipherAES256} config := &packet.Config{DefaultCipher: packet.CipherAES256}
symKey := make([]byte, size) symKey := make([]byte, size)
@ -55,7 +55,8 @@ func RandomToken(size int) ([]byte, error) {
return symKey, nil return symKey, nil
} }
// GenerateSessionKeyAlgo generates a random key of the correct length for the specified algorithm // GenerateSessionKeyAlgo generates a random key of the correct length for the
// specified algorithm.
func GenerateSessionKeyAlgo(algo string) (sk *SessionKey, err error) { func GenerateSessionKeyAlgo(algo string) (sk *SessionKey, err error) {
cf, ok := symKeyAlgos[algo] cf, ok := symKeyAlgos[algo]
if !ok { if !ok {
@ -73,7 +74,7 @@ func GenerateSessionKeyAlgo(algo string) (sk *SessionKey, err error) {
return sk, nil return sk, nil
} }
// GenerateSessionKey generates a random key for the default cipher // GenerateSessionKey generates a random key for the default cipher.
func GenerateSessionKey() (*SessionKey, error) { func GenerateSessionKey() (*SessionKey, error) {
return GenerateSessionKeyAlgo(constants.AES256) return GenerateSessionKeyAlgo(constants.AES256)
} }
@ -105,9 +106,9 @@ func newSessionKeyFromEncrypted(ek *packet.EncryptedKey) (*SessionKey, error) {
return symmetricKey, nil return symmetricKey, nil
} }
// Encrypt encrypts a PlainMessage to PGPMessage with a SessionKey // Encrypt encrypts a PlainMessage to PGPMessage with a SessionKey.
// * message : The plain data as a PlainMessage // * message : The plain data as a PlainMessage.
// * output : The encrypted data as PGPMessage // * output : The encrypted data as PGPMessage.
func (sk *SessionKey) Encrypt(message *PlainMessage) ([]byte, error) { func (sk *SessionKey) Encrypt(message *PlainMessage) ([]byte, error) {
var encBuf bytes.Buffer var encBuf bytes.Buffer
var encryptWriter io.WriteCloser var encryptWriter io.WriteCloser
@ -152,9 +153,9 @@ func (sk *SessionKey) Encrypt(message *PlainMessage) ([]byte, error) {
return encBuf.Bytes(), nil return encBuf.Bytes(), nil
} }
// Decrypt decrypts password protected pgp binary messages // Decrypt decrypts password protected pgp binary messages.
// * encrypted: PGPMessage // * encrypted: PGPMessage.
// * output: PlainMessage // * output: PlainMessage.
func (sk *SessionKey) Decrypt(dataPacket []byte) (*PlainMessage, error) { func (sk *SessionKey) Decrypt(dataPacket []byte) (*PlainMessage, error) {
var messageReader = bytes.NewReader(dataPacket) var messageReader = bytes.NewReader(dataPacket)
var decrypted io.ReadCloser var decrypted io.ReadCloser

View file

@ -15,13 +15,14 @@ import (
"github.com/ProtonMail/gopenpgp/v2/internal" "github.com/ProtonMail/gopenpgp/v2/internal"
) )
// SignatureVerificationError is returned from Decrypt and VerifyDetached functions when signature verification fails // SignatureVerificationError is returned from Decrypt and VerifyDetached
// functions when signature verification fails.
type SignatureVerificationError struct { type SignatureVerificationError struct {
Status int Status int
Message string Message string
} }
// Error is the base method for all errors // Error is the base method for all errors.
func (e SignatureVerificationError) Error() string { func (e SignatureVerificationError) Error() string {
return fmt.Sprintf("Signature Verification Error: %v", e.Message) return fmt.Sprintf("Signature Verification Error: %v", e.Message)
} }
@ -30,7 +31,8 @@ func (e SignatureVerificationError) Error() string {
// Internal functions // Internal functions
// ------------------ // ------------------
// newSignatureFailed creates a new SignatureVerificationError, type SIGNATURE_FAILED // newSignatureFailed creates a new SignatureVerificationError, type
// SignatureFailed.
func newSignatureFailed() SignatureVerificationError { func newSignatureFailed() SignatureVerificationError {
return SignatureVerificationError{ return SignatureVerificationError{
constants.SIGNATURE_FAILED, constants.SIGNATURE_FAILED,
@ -38,7 +40,8 @@ func newSignatureFailed() SignatureVerificationError {
} }
} }
// newSignatureNotSigned creates a new SignatureVerificationError, type SIGNATURE_NOT_SIGNED // newSignatureNotSigned creates a new SignatureVerificationError, type
// SignatureNotSigned.
func newSignatureNotSigned() SignatureVerificationError { func newSignatureNotSigned() SignatureVerificationError {
return SignatureVerificationError{ return SignatureVerificationError{
constants.SIGNATURE_NOT_SIGNED, constants.SIGNATURE_NOT_SIGNED,
@ -46,7 +49,8 @@ func newSignatureNotSigned() SignatureVerificationError {
} }
} }
// newSignatureNoVerifier creates a new SignatureVerificationError, type SIGNATURE_NO_VERIFIER // newSignatureNoVerifier creates a new SignatureVerificationError, type
// SignatureNoVerifier.
func newSignatureNoVerifier() SignatureVerificationError { func newSignatureNoVerifier() SignatureVerificationError {
return SignatureVerificationError{ return SignatureVerificationError{
constants.SIGNATURE_NO_VERIFIER, constants.SIGNATURE_NO_VERIFIER,
@ -54,50 +58,46 @@ func newSignatureNoVerifier() SignatureVerificationError {
} }
} }
// processSignatureExpiration handles signature time verification manually, so we can add a margin to the // processSignatureExpiration handles signature time verification manually, so
// creationTime check. // we can add a margin to the creationTime check.
func processSignatureExpiration(md *openpgp.MessageDetails, verifyTime int64) { func processSignatureExpiration(md *openpgp.MessageDetails, verifyTime int64) {
if md.SignatureError == pgpErrors.ErrSignatureExpired { if md.SignatureError != pgpErrors.ErrSignatureExpired {
if verifyTime > 0 { return
created := md.Signature.CreationTime.Unix() }
expires := int64(math.MaxInt64) if verifyTime == 0 {
if md.Signature.SigLifetimeSecs != nil { // verifyTime = 0: time check disabled, everything is okay
expires = int64(*md.Signature.SigLifetimeSecs) + created md.SignatureError = nil
} return
if created-internal.CreationTimeOffset <= verifyTime && verifyTime <= expires { }
md.SignatureError = nil created := md.Signature.CreationTime.Unix()
} expires := int64(math.MaxInt64)
} else { if md.Signature.SigLifetimeSecs != nil {
// verifyTime = 0: time check disabled, everything is okay expires = int64(*md.Signature.SigLifetimeSecs) + created
md.SignatureError = nil }
} if created-internal.CreationTimeOffset <= verifyTime && verifyTime <= expires {
md.SignatureError = nil
} }
} }
// verifyDetailsSignature verifies signature from message details // verifyDetailsSignature verifies signature from message details.
func verifyDetailsSignature(md *openpgp.MessageDetails, verifierKey *KeyRing) error { func verifyDetailsSignature(md *openpgp.MessageDetails, verifierKey *KeyRing) error {
if md.IsSigned { if md.IsSigned {
if md.SignedBy != nil { if md.SignedBy == nil || len(verifierKey.entities) == 0 {
if len(verifierKey.entities) > 0 {
matches := verifierKey.entities.KeysById(md.SignedByKeyId)
if len(matches) > 0 {
if md.SignatureError == nil {
return nil
}
return newSignatureFailed()
}
} else {
return newSignatureNoVerifier()
}
} else {
return newSignatureNoVerifier() return newSignatureNoVerifier()
} }
matches := verifierKey.entities.KeysById(md.SignedByKeyId)
if len(matches) > 0 {
if md.SignatureError == nil {
return nil
}
return newSignatureFailed()
}
} }
return newSignatureNoVerifier() return newSignatureNoVerifier()
} }
// verifySignature verifies if a signature is valid with the entity list // verifySignature verifies if a signature is valid with the entity list.
func verifySignature(pubKeyEntries openpgp.EntityList, origText io.Reader, signature []byte, verifyTime int64) error { func verifySignature(pubKeyEntries openpgp.EntityList, origText io.Reader, signature []byte, verifyTime int64) error {
config := &packet.Config{} config := &packet.Config{}
if verifyTime == 0 { if verifyTime == 0 {
@ -113,23 +113,22 @@ func verifySignature(pubKeyEntries openpgp.EntityList, origText io.Reader, signa
signer, err := openpgp.CheckDetachedSignature(pubKeyEntries, origText, signatureReader, config) signer, err := openpgp.CheckDetachedSignature(pubKeyEntries, origText, signatureReader, config)
if err == pgpErrors.ErrSignatureExpired && signer != nil { if err == pgpErrors.ErrSignatureExpired && signer != nil && verifyTime > 0 {
if verifyTime > 0 { // if verifyTime = 0: time check disabled, everything is okay // if verifyTime = 0: time check disabled, everything is okay
// Maybe the creation time offset pushed it over the edge // Maybe the creation time offset pushed it over the edge
// Retry with the actual verification time // Retry with the actual verification time
config.Time = func() time.Time { config.Time = func() time.Time {
return time.Unix(verifyTime, 0) return time.Unix(verifyTime, 0)
} }
_, err = signatureReader.Seek(0, io.SeekStart) _, err = signatureReader.Seek(0, io.SeekStart)
if err != nil { if err != nil {
return newSignatureFailed() return newSignatureFailed()
} }
signer, err = openpgp.CheckDetachedSignature(pubKeyEntries, origText, signatureReader, config) signer, err = openpgp.CheckDetachedSignature(pubKeyEntries, origText, signatureReader, config)
if err != nil { if err != nil {
return newSignatureFailed() return newSignatureFailed()
}
} }
} }

View file

@ -13,7 +13,7 @@ import (
"golang.org/x/crypto/openpgp/packet" "golang.org/x/crypto/openpgp/packet"
) )
// SignatureCollector structure // SignatureCollector structure.
type SignatureCollector struct { type SignatureCollector struct {
config *packet.Config config *packet.Config
keyring openpgp.KeyRing keyring openpgp.KeyRing
@ -32,91 +32,85 @@ func newSignatureCollector(
} }
} }
// Accept collects the signature // Accept collects the signature.
func (sc *SignatureCollector) Accept( func (sc *SignatureCollector) Accept(
part io.Reader, header textproto.MIMEHeader, part io.Reader, header textproto.MIMEHeader,
hasPlainSibling, isFirst, isLast bool, hasPlainSibling, isFirst, isLast bool,
) (err error) { ) (err error) {
parentMediaType, params, _ := mime.ParseMediaType(header.Get("Content-Type")) parentMediaType, params, _ := mime.ParseMediaType(header.Get("Content-Type"))
if parentMediaType == "multipart/signed" {
newPart, rawBody := gomime.GetRawMimePart(part, "--"+params["boundary"])
var multiparts []io.Reader
var multipartHeaders []textproto.MIMEHeader
if multiparts, multipartHeaders, err = gomime.GetMultipartParts(newPart, params); err == nil {
hasPlainChild := false
for _, header := range multipartHeaders {
mediaType, _, _ := mime.ParseMediaType(header.Get("Content-Type"))
if mediaType == "text/plain" {
hasPlainChild = true
}
}
if len(multiparts) != 2 {
sc.verified = newSignatureNotSigned()
// Invalid multipart/signed format just pass along
_, err = ioutil.ReadAll(rawBody)
if err != nil {
return err
}
for i, p := range multiparts { if parentMediaType != "multipart/signed" {
if err = sc.target.Accept(p, multipartHeaders[i], hasPlainChild, true, true); err != nil { return sc.target.Accept(part, header, hasPlainSibling, isFirst, isLast)
return }
}
} newPart, rawBody := gomime.GetRawMimePart(part, "--"+params["boundary"])
multiparts, multipartHeaders, err := gomime.GetMultipartParts(newPart, params)
if err != nil {
return
}
hasPlainChild := false
for _, header := range multipartHeaders {
mediaType, _, _ := mime.ParseMediaType(header.Get("Content-Type"))
hasPlainChild = (mediaType == "text/plain")
}
if len(multiparts) != 2 {
sc.verified = newSignatureNotSigned()
// Invalid multipart/signed format just pass along
if _, err = ioutil.ReadAll(rawBody); err != nil {
return err
}
for i, p := range multiparts {
if err = sc.target.Accept(p, multipartHeaders[i], hasPlainChild, true, true); err != nil {
return return
} }
// actual multipart/signed format
err = sc.target.Accept(multiparts[0], multipartHeaders[0], hasPlainChild, true, true)
if err != nil {
return err
}
partData, err := ioutil.ReadAll(multiparts[1])
if err != nil {
return err
}
decodedPart := gomime.DecodeContentEncoding(
bytes.NewReader(partData),
multipartHeaders[1].Get("Content-Transfer-Encoding"))
buffer, err := ioutil.ReadAll(decodedPart)
if err != nil {
return err
}
mediaType, _, _ := mime.ParseMediaType(header.Get("Content-Type"))
buffer, err = gomime.DecodeCharset(buffer, mediaType, params)
if err != nil {
return err
}
sc.signature = string(buffer)
str, _ := ioutil.ReadAll(rawBody)
rawBody = bytes.NewReader(str)
if sc.keyring != nil {
_, err = openpgp.CheckArmoredDetachedSignature(sc.keyring, rawBody, bytes.NewReader(buffer), sc.config)
if err != nil {
sc.verified = newSignatureFailed()
} else {
sc.verified = nil
}
} else {
sc.verified = newSignatureNoVerifier()
}
return nil
} }
return return
} }
err = sc.target.Accept(part, header, hasPlainSibling, isFirst, isLast)
// actual multipart/signed format
err = sc.target.Accept(multiparts[0], multipartHeaders[0], hasPlainChild, true, true)
if err != nil { if err != nil {
return err return err
} }
return nil partData, err := ioutil.ReadAll(multiparts[1])
if err != nil {
return err
}
decodedPart := gomime.DecodeContentEncoding(
bytes.NewReader(partData),
multipartHeaders[1].Get("Content-Transfer-Encoding"))
buffer, err := ioutil.ReadAll(decodedPart)
if err != nil {
return err
}
mediaType, _, _ := mime.ParseMediaType(header.Get("Content-Type"))
buffer, err = gomime.DecodeCharset(buffer, mediaType, params)
if err != nil {
return err
}
sc.signature = string(buffer)
str, _ := ioutil.ReadAll(rawBody)
rawBody = bytes.NewReader(str)
if sc.keyring != nil {
_, err = openpgp.CheckArmoredDetachedSignature(sc.keyring, rawBody, bytes.NewReader(buffer), sc.config)
if err != nil {
sc.verified = newSignatureFailed()
} else {
sc.verified = nil
}
} else {
sc.verified = newSignatureNoVerifier()
}
return err
} }
// GetSignature collected by Accept // GetSignature collected by Accept.
func (sc SignatureCollector) GetSignature() string { func (sc SignatureCollector) GetSignature() string {
return sc.signature return sc.signature
} }

View file

@ -5,25 +5,25 @@ import (
"time" "time"
) )
// UpdateTime updates cached time // UpdateTime updates cached time.
func UpdateTime(newTime int64) { func UpdateTime(newTime int64) {
pgp.latestServerTime = newTime pgp.latestServerTime = newTime
pgp.latestClientTime = time.Now() pgp.latestClientTime = time.Now()
} }
// GetUnixTime gets latest cached time // GetUnixTime gets latest cached time.
func GetUnixTime() int64 { func GetUnixTime() int64 {
return getNow().Unix() return getNow().Unix()
} }
// GetTime gets latest cached time // GetTime gets latest cached time.
func GetTime() time.Time { func GetTime() time.Time {
return getNow() return getNow()
} }
// ----- INTERNAL FUNCTIONS ----- // ----- INTERNAL FUNCTIONS -----
// getNow returns current time // getNow returns current time.
func getNow() time.Time { func getNow() time.Time {
extrapolate, err := getDiff() extrapolate, err := getDiff()
@ -43,7 +43,7 @@ func getDiff() (int64, error) {
return 0, errors.New("gopenpgp: latest server time not available") return 0, errors.New("gopenpgp: latest server time not available")
} }
// getTimeGenerator Returns a time generator function // getTimeGenerator Returns a time generator function.
func getTimeGenerator() func() time.Time { func getTimeGenerator() func() time.Time {
return getNow return getNow
} }

View file

@ -7,8 +7,9 @@ import (
"github.com/ProtonMail/gopenpgp/v2/internal" "github.com/ProtonMail/gopenpgp/v2/internal"
) )
// SignCleartextMessageArmored signs text given a private key and its passphrase, canonicalizes and trims the newlines, // SignCleartextMessageArmored signs text given a private key and its
// and returns the PGP-compliant special armoring // passphrase, canonicalizes and trims the newlines, and returns the
// PGP-compliant special armoring.
func SignCleartextMessageArmored(privateKey string, passphrase []byte, text string) (string, error) { func SignCleartextMessageArmored(privateKey string, passphrase []byte, text string) (string, error) {
signingKey, err := crypto.NewKeyFromArmored(privateKey) signingKey, err := crypto.NewKeyFromArmored(privateKey)
if err != nil { if err != nil {
@ -29,8 +30,9 @@ func SignCleartextMessageArmored(privateKey string, passphrase []byte, text stri
return SignCleartextMessage(keyRing, text) return SignCleartextMessage(keyRing, text)
} }
// VerifyCleartextMessageArmored verifies PGP-compliant armored signed plain text given the public key // VerifyCleartextMessageArmored verifies PGP-compliant armored signed plain
// and returns the text or err if the verification fails // text given the public key and returns the text or err if the verification
// fails.
func VerifyCleartextMessageArmored(publicKey, armored string, verifyTime int64) (string, error) { func VerifyCleartextMessageArmored(publicKey, armored string, verifyTime int64) (string, error) {
signingKey, err := crypto.NewKeyFromArmored(publicKey) signingKey, err := crypto.NewKeyFromArmored(publicKey)
if err != nil { if err != nil {
@ -45,8 +47,8 @@ func VerifyCleartextMessageArmored(publicKey, armored string, verifyTime int64)
return VerifyCleartextMessage(verifyKeyRing, armored, verifyTime) return VerifyCleartextMessage(verifyKeyRing, armored, verifyTime)
} }
// SignCleartextMessage signs text given a private keyring, canonicalizes and trims the newlines, // SignCleartextMessage signs text given a private keyring, canonicalizes and
// and returns the PGP-compliant special armoring // trims the newlines, and returns the PGP-compliant special armoring.
func SignCleartextMessage(keyRing *crypto.KeyRing, text string) (string, error) { func SignCleartextMessage(keyRing *crypto.KeyRing, text string) (string, error) {
text = canonicalizeAndTrim(text) text = canonicalizeAndTrim(text)
message := crypto.NewPlainMessageFromString(text) message := crypto.NewPlainMessageFromString(text)
@ -59,8 +61,9 @@ func SignCleartextMessage(keyRing *crypto.KeyRing, text string) (string, error)
return crypto.NewClearTextMessage(message.GetBinary(), signature.GetBinary()).GetArmored() return crypto.NewClearTextMessage(message.GetBinary(), signature.GetBinary()).GetArmored()
} }
// VerifyCleartextMessage verifies PGP-compliant armored signed plain text given the public keyring // VerifyCleartextMessage verifies PGP-compliant armored signed plain text
// and returns the text or err if the verification fails // 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) { func VerifyCleartextMessage(keyRing *crypto.KeyRing, armored string, verifyTime int64) (string, error) {
clearTextMessage, err := crypto.NewClearTextMessageFromArmored(armored) clearTextMessage, err := crypto.NewClearTextMessageFromArmored(armored)
if err != nil { if err != nil {
@ -79,7 +82,7 @@ func VerifyCleartextMessage(keyRing *crypto.KeyRing, armored string, verifyTime
// ----- INTERNAL FUNCTIONS ----- // ----- INTERNAL FUNCTIONS -----
// canonicalizeAndTrim alters a string canonicalizing and trimming the newlines // canonicalizeAndTrim alters a string canonicalizing and trimming the newlines.
func canonicalizeAndTrim(text string) string { func canonicalizeAndTrim(text string) string {
text = internal.TrimNewlines(text) text = internal.TrimNewlines(text)
text = strings.Replace(strings.Replace(text, "\r\n", "\n", -1), "\n", "\r\n", -1) text = strings.Replace(strings.Replace(text, "\r\n", "\n", -1), "\n", "\r\n", -1)

View file

@ -1,4 +1,4 @@
// helper contains several functions with a simple interface to extend usability and compatibility with gomobile // Package helper contains several functions with a simple interface to extend usability and compatibility with gomobile
package helper package helper
import ( import (
@ -7,7 +7,7 @@ import (
"github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/gopenpgp/v2/crypto"
) )
// EncryptMessageWithPassword encrypts a string with a passphrase using AES256 // EncryptMessageWithPassword encrypts a string with a passphrase using AES256.
func EncryptMessageWithPassword(password []byte, plaintext string) (ciphertext string, err error) { func EncryptMessageWithPassword(password []byte, plaintext string) (ciphertext string, err error) {
var pgpMessage *crypto.PGPMessage var pgpMessage *crypto.PGPMessage
@ -41,7 +41,8 @@ func DecryptMessageWithPassword(password []byte, ciphertext string) (plaintext s
return message.GetString(), nil return message.GetString(), nil
} }
// EncryptMessageArmored generates an armored PGP message given a plaintext and an armored public key // EncryptMessageArmored generates an armored PGP message given a plaintext and
// an armored public key.
func EncryptMessageArmored(key, plaintext string) (ciphertext string, err error) { func EncryptMessageArmored(key, plaintext string) (ciphertext string, err error) {
var publicKey *crypto.Key var publicKey *crypto.Key
var publicKeyRing *crypto.KeyRing var publicKeyRing *crypto.KeyRing
@ -68,8 +69,8 @@ func EncryptMessageArmored(key, plaintext string) (ciphertext string, err error)
return ciphertext, nil return ciphertext, nil
} }
// EncryptSignMessageArmored generates an armored signed PGP message given a plaintext and an armored public key // EncryptSignMessageArmored generates an armored signed PGP message given a
// a private key and its passphrase // plaintext and an armored public key a private key and its passphrase.
func EncryptSignMessageArmored( func EncryptSignMessageArmored(
publicKey, privateKey string, passphrase []byte, plaintext string, publicKey, privateKey string, passphrase []byte, plaintext string,
) (ciphertext string, err error) { ) (ciphertext string, err error) {
@ -111,7 +112,8 @@ func EncryptSignMessageArmored(
return ciphertext, nil return ciphertext, nil
} }
// DecryptMessageArmored decrypts an armored PGP message given a private key and its passphrase // DecryptMessageArmored decrypts an armored PGP message given a private key
// and its passphrase.
func DecryptMessageArmored( func DecryptMessageArmored(
privateKey string, passphrase []byte, ciphertext string, privateKey string, passphrase []byte, ciphertext string,
) (plaintext string, err error) { ) (plaintext string, err error) {
@ -144,9 +146,9 @@ func DecryptMessageArmored(
return message.GetString(), nil return message.GetString(), nil
} }
// DecryptVerifyMessageArmored decrypts an armored PGP message given a private key and its passphrase // DecryptVerifyMessageArmored decrypts an armored PGP message given a private
// and verifies the embedded signature. // key and its passphrase and verifies the embedded signature. Returns the
// Returns the plain data or an error on signature verification failure. // plain data or an error on signature verification failure.
func DecryptVerifyMessageArmored( func DecryptVerifyMessageArmored(
publicKey, privateKey string, passphrase []byte, ciphertext string, publicKey, privateKey string, passphrase []byte, ciphertext string,
) (plaintext string, err error) { ) (plaintext string, err error) {
@ -187,9 +189,10 @@ func DecryptVerifyMessageArmored(
return message.GetString(), nil return message.GetString(), nil
} }
// DecryptVerifyAttachment decrypts and verifies an attachment split into the keyPacket, dataPacket // DecryptVerifyAttachment decrypts and verifies an attachment split into the
// and an armored (!) signature, given a publicKey, and a privateKey with its passphrase. // keyPacket, dataPacket and an armored (!) signature, given a publicKey, and a
// Returns the plain data or an error on signature verification failure. // privateKey with its passphrase. Returns the plain data or an error on
// signature verification failure.
func DecryptVerifyAttachment( func DecryptVerifyAttachment(
publicKey, privateKey string, publicKey, privateKey string,
passphrase, keyPacket, dataPacket []byte, passphrase, keyPacket, dataPacket []byte,

View file

@ -11,9 +11,9 @@ type ExplicitVerifyMessage struct {
SignatureVerificationError *crypto.SignatureVerificationError 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 verifies the embedded signature. // and its passphrase and verifies the embedded signature. Returns the plain
// Returns the plain data or an error on signature verification failure. // data or an error on signature verification failure.
func DecryptExplicitVerify( func DecryptExplicitVerify(
pgpMessage *crypto.PGPMessage, pgpMessage *crypto.PGPMessage,
privateKeyRing, publicKeyRing *crypto.KeyRing, privateKeyRing, publicKeyRing *crypto.KeyRing,
@ -57,8 +57,9 @@ func DecryptAttachment(keyPacket []byte, dataPacket []byte, keyRing *crypto.KeyR
} }
// EncryptAttachment encrypts a file given a plainData and a fileName. // EncryptAttachment encrypts a file given a plainData and a fileName.
// Returns a PGPSplitMessage containing a session key packet and symmetrically encrypted data. // Returns a PGPSplitMessage containing a session key packet and symmetrically
// Specifically designed for attachments rather than text messages. // encrypted data. Specifically designed for attachments rather than text
// messages.
func EncryptAttachment(plainData []byte, fileName string, keyRing *crypto.KeyRing) (*crypto.PGPSplitMessage, error) { func EncryptAttachment(plainData []byte, fileName string, keyRing *crypto.KeyRing) (*crypto.PGPSplitMessage, error) {
plainMessage := crypto.NewPlainMessage(plainData) plainMessage := crypto.NewPlainMessage(plainData)
decrypted, err := keyRing.EncryptAttachment(plainMessage, fileName) decrypted, err := keyRing.EncryptAttachment(plainMessage, fileName)
@ -68,8 +69,8 @@ func EncryptAttachment(plainData []byte, fileName string, keyRing *crypto.KeyRin
return decrypted, nil return decrypted, nil
} }
// GetJsonSHA256Fingerprints returns the SHA256 fingeprints of key and subkeys, encoded in JSON, since gomobile can not // GetJsonSHA256Fingerprints returns the SHA256 fingeprints of key and subkeys,
// handle arrays // encoded in JSON, since gomobile can not handle arrays.
func GetJsonSHA256Fingerprints(publicKey string) ([]byte, error) { func GetJsonSHA256Fingerprints(publicKey string) ([]byte, error) {
key, err := crypto.NewKeyFromArmored(publicKey) key, err := crypto.NewKeyFromArmored(publicKey)
if err != nil { if err != nil {