Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Version 2 Update
This document summarizes the major changes introduced by
ProtonMail/go-crypto/v2
compared to
ProtonMail/go-crypto
.Import
V2 can be imported as:
API breaking changes
openpgp.Entity
struct fields have changed:SelfSignature *packet.Signature
removedSignatures []*packet.Signature
removedDirectSignatures []*packet.VerifiableSignature
addedRevocations []*packet.VerifiableSignature
changed typeopenpgp.Entity
changed API methods:PrimaryIdentity(date time.Time)
has a time argument now.EncryptionKey(date time.Time, config *packet.Config)
has a new config argument.CertificationKey(date time.Time, config *packet.Config)
has a new config argument.CertificationKeyById(date time.Time, id uint64, config *packet.Config)
has a new config argument.SigningKey(date time.Time, config *packet.Config)
has a new config argument.SigningKeyById(date time.Time, id uint64, config *packet.Config)
has a new config argument.Revoke(reason packet.ReasonForRevocation, reasonText string, config *packet.Config)
changed name instead of RevokeKey.Entity
removed API methods:RevokeSubkey(...)
replaced by(Subkey).Revoke(...)
openpgp.Subkey
struct fields have changed:Sig *packet.Signature
removedBindings []*packet.VerifiableSignature
addedPrimary *Entity
added, points to the primary key.Revocations []*packet.VerifiableSignature
changed typeopenpgp.Subkey
changed API methods:Revoked(selfCertification *packet.Signature, date time.Time)
has a new selfCertification argument, which points to the self signature to be used.Identity
struct fields have changed:SelfSignature *packet.Signature
removedSignatures []*packet.Signature
removedSelfCertifications []*packet.VerifiableSignature
addedOtherCertifications []*packet.VerifiableSignature
addedPrimary *Entity
added, points to the primary key.Revocations []*packet.VerifiableSignature
changed typeopenpgp.Identity
changed API methods:Revoked(selfCertification *packet.Signature, date time.Time)
has a new selfCertification argument, which points to the self signature to be used.openpgp.Key
struct fields have changed:PrimarySelfSignature *packet.Signature
added, which points to the selected self signature of the primary key.Revocations []*packet.VerifiableSignature
changed typeopenpgp.KeyRing
interface has has changed:KeysByIdUsage(...)
removedDecryptionKeys(...)
removedEntitiesById(id uint64) []*Entity
added. This is the main internal method to access keys from the keyring now.openpgp.FileHints
struct field has changed:IsBinary
removed andIsUTF8
addedopenpgp
API changes for reading messages:VerifyDetachedSignatureAndHash(...)
removed, headers in clearsigned messages are no longer checked.VerifyDetachedSignatureAndSaltedHash(...)
removedCheckDetachedSignature(...)
removed, callVerifyDetachedSignature(...)
insteadCheckDetachedSignatureAndSaltedHash(...)
removedCheckDetachedSignatureAndHash(...)
removedCheckArmoredDetachedSignature
removed callVerifyArmoredDetachedSignature
insteadopenpgp
API changes for writing messages:DetachSign(..., signers []*Entity,...)
takes now a slice of entities instead of a single entity as an argument.ArmoredDetachSign(..., signers []*Entity,...)
takes now a slice of entities instead of a single entity as an argument.DetachSignText(..., signers []*Entity,...)
takes now a slice of entities instead of a single entity as an argument.ArmoredDetachSignText(..., signers []*Entity,...)
takes now a slice of entities instead of a single entity as an argument.EncryptText(...)
removed callEncryptWithParams(...)
insteadEncryptSplit(...)
removed callEncryptWithParams(...)
insteadEncryptTextSplit(...)
removed callEncryptWithParams(...)
insteadEncrypt(..., toHidden []*Entity, signers []*Entity)
now takes an additional toHidden recipients argument and takes now a slice of signer entities instead of a single entity as an argument.Sign(..., signers []*Entity,...)
takes now a slice of entities instead of a single entity as an argument.clearsign
changed API methods:Encode(w io.Writer, privateKey *packet.PrivateKey, config *packet.Config, headers map[string]string)
has new headers argument.EncodeMulti(w io.Writer, privateKeys []*packet.PrivateKey, config *packet.Config, headers map[string]string)
has new headers argument.packet
changed API methods:SerializeEncryptedKeyAEAD(..., hidden bool, ...)
has new hidden argument, which indicates that the packet should not contain a key identifier.SerializeEncryptedKey(..., hidden bool, ...)
has new hidden argument, see above.packet.LiteralData
struct field has changed:IsBinary
is renamed toIsUTF8
packet.SymmetricallyEncrypted
struct field has changed:cipher
is now publicCipher
Features added
Intended recipients
Version 2 of the ProtonMail/go-crypto library introduces a feature for including the recipients' key fingerprints in signatures during message encryption.
When encrypting and signing a message, the intended recipients are automatically included in the signature, unless specifically hidden (i.e., hidden recipients).
During the decryption process, if the signature contains intended recipients and the appropriate configuration flag is set, the library verifies whether the primary ID of the decryption key is present in the recipient list.
This check can be disabled in the config when a hidden recipient decrypts the message.
Multi-signature support
In previous iterations of ProtonMail/go-crypto, only a single signature creation and verification were supported in a PGP message.
However, in Version 2, the library introduces the ability to sign messages with multiple signatures using different keys, such as a v4 and a v6 key.
The encryption and signing methods now accept multiple signing keys as arguments, with each key designated for a specific signature.
When reading PGP messages with Version 2, the library maintains an internal state for each known signature and verifies all of them within the message.
To facilitate this functionality, the message details struct includes a new field that stores the verification state for each signature. A message is considered valid if at least one of the signatures successfully validates without any errors.
For callers, the process of checking for signature errors remains similar to previous versions.
However, if the caller requires the verification state of all signatures, they can utilize the new field in the message details struct.
Rework how signatures in keys and signatures are verified
In previous iterations of ProtonMail/go-crypto, key verification occurred during import based on the current time, while signature verification did not involve further key checks.
However, this approach had limitations, as invalid keys could have been valid at the time of signature creation and mistakenly considered invalid.
Version 2 changes how and when signatures are verified in keys (i.e., direct-signatures, self-signatures of userids, binding signatures in subkeys, revocations, etc).
Unlike before, key signature verification no longer takes place during parsing.
Instead, keys are now validated when they are utilized, following a similar approach to key handling in OpenPGP.js.
Additionally, all signatures and expirations are validated to adhere to the key lifecycle outlined in the RFC.
The validity of keys can now be checked at different points in time, leading to the following specific modifications:
Further, version 2 includes various small improvements to increase the robustness of the key parsing functions.
Weak algorithm rejection
Version 2 introduces the option to specify weak algorithms for signatures in the config.
Signatures that use weak algorithms are considered invalid.
Optional packet sequence checker
Version 2 introduces a new feature that enables the validation of packet sequences in PGP messages.
This functionality can be enabled in the config struct.
In particular, it implements the pushdown automata (PDA) from PGPainless, developed by Paul Schaub.
By leveraging this feature, users can ensure that the packet sequences in their PGP messages are valid and comply with the required structure.
This addition further enhances the overall reliability and security of PGP message handling in Version 2.
Session key encryption and decryption
Version 2 allows advanced users to retrieve the session key while encrypting a message by setting the respective flag in the config.
In decryption, a caller can provide a session key that should be used for decryption.
Unify write/read API
Version 2 improves the compatibility between different APIs to allow combinations.
The
DetachSign
function requires the caller to provide aReader
for the message, whileencrypt returns a
WriteCloser
to which the message is written to.The new version adds a function
DetachSignWriter
, which returns aWriteCloser
similar to the encryption API.On the reading side, the verify detached signature API now relies on the
same signature verification logic as the other read functions.
Additionally, a new
VerifyDetachedSignatureReader
method similar to theReadMessage
API is introduced.It returns a message details struct that once read verifies the signature.
Allows to chain different readers from the API, for example, to have a streaming API for encrypted detached signatures.
Params struct as a function argument in the write API
With the inclusion of new features, the write functions in go-crypto experienced significant growth in numbers. Each combination has its dedicated function.
Version 2 introduces an
EncryptWithParams
/SignWithParams
function that takes anEncryptParams
/SignParams
struct as an argument. The struct allows configuring the different features.This approach effectively reduces the number of API methods and simplifies the process of adding new features while maintaining compatibility with previous versions.
Others
armor.Encode
methodunarmor
more robust to empty header valuesIdentity