We were running behind and there were quite some deprecations to update. This was mostly in the upstream copy/pasta package but seems quite minimal.
423 lines
14 KiB
Go
423 lines
14 KiB
Go
// Copyright 2012 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package packet
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/rand"
|
|
"io"
|
|
"math/big"
|
|
"time"
|
|
|
|
"github.com/ProtonMail/go-crypto/openpgp/s2k"
|
|
)
|
|
|
|
var (
|
|
defaultRejectPublicKeyAlgorithms = map[PublicKeyAlgorithm]bool{
|
|
PubKeyAlgoElGamal: true,
|
|
PubKeyAlgoDSA: true,
|
|
}
|
|
defaultRejectHashAlgorithms = map[crypto.Hash]bool{
|
|
crypto.MD5: true,
|
|
crypto.RIPEMD160: true,
|
|
}
|
|
defaultRejectMessageHashAlgorithms = map[crypto.Hash]bool{
|
|
crypto.SHA1: true,
|
|
crypto.MD5: true,
|
|
crypto.RIPEMD160: true,
|
|
}
|
|
defaultRejectCurves = map[Curve]bool{
|
|
CurveSecP256k1: true,
|
|
}
|
|
)
|
|
|
|
// A global feature flag to indicate v5 support.
|
|
// Can be set via a build tag, e.g.: `go build -tags v5 ./...`
|
|
// If the build tag is missing config_v5.go will set it to true.
|
|
//
|
|
// Disables parsing of v5 keys and v5 signatures.
|
|
// These are non-standard entities, which in the crypto-refresh have been superseded
|
|
// by v6 keys, v6 signatures and SEIPDv2 encrypted data, respectively.
|
|
var V5Disabled = false
|
|
|
|
// Config collects a number of parameters along with sensible defaults.
|
|
// A nil *Config is valid and results in all default values.
|
|
type Config struct {
|
|
// Rand provides the source of entropy.
|
|
// If nil, the crypto/rand Reader is used.
|
|
Rand io.Reader
|
|
// DefaultHash is the default hash function to be used.
|
|
// If zero, SHA-256 is used.
|
|
DefaultHash crypto.Hash
|
|
// DefaultCipher is the cipher to be used.
|
|
// If zero, AES-128 is used.
|
|
DefaultCipher CipherFunction
|
|
// Time returns the current time as the number of seconds since the
|
|
// epoch. If Time is nil, time.Now is used.
|
|
Time func() time.Time
|
|
// DefaultCompressionAlgo is the compression algorithm to be
|
|
// applied to the plaintext before encryption. If zero, no
|
|
// compression is done.
|
|
DefaultCompressionAlgo CompressionAlgo
|
|
// CompressionConfig configures the compression settings.
|
|
CompressionConfig *CompressionConfig
|
|
// S2K (String to Key) config, used for key derivation in the context of secret key encryption
|
|
// and password-encrypted data.
|
|
// If nil, the default configuration is used
|
|
S2KConfig *s2k.Config
|
|
// Iteration count for Iterated S2K (String to Key).
|
|
// Only used if sk2.Mode is nil.
|
|
// This value is duplicated here from s2k.Config for backwards compatibility.
|
|
// It determines the strength of the passphrase stretching when
|
|
// the said passphrase is hashed to produce a key. S2KCount
|
|
// should be between 65536 and 65011712, inclusive. If Config
|
|
// is nil or S2KCount is 0, the value 16777216 used. Not all
|
|
// values in the above range can be represented. S2KCount will
|
|
// be rounded up to the next representable value if it cannot
|
|
// be encoded exactly. When set, it is strongly encrouraged to
|
|
// use a value that is at least 65536. See RFC 4880 Section
|
|
// 3.7.1.3.
|
|
//
|
|
// Deprecated: SK2Count should be configured in S2KConfig instead.
|
|
S2KCount int
|
|
// RSABits is the number of bits in new RSA keys made with NewEntity.
|
|
// If zero, then 2048 bit keys are created.
|
|
RSABits int
|
|
// The public key algorithm to use - will always create a signing primary
|
|
// key and encryption subkey.
|
|
Algorithm PublicKeyAlgorithm
|
|
// Some known primes that are optionally prepopulated by the caller
|
|
RSAPrimes []*big.Int
|
|
// Curve configures the desired packet.Curve if the Algorithm is PubKeyAlgoECDSA,
|
|
// PubKeyAlgoEdDSA, or PubKeyAlgoECDH. If empty Curve25519 is used.
|
|
Curve Curve
|
|
// AEADConfig configures the use of the new AEAD Encrypted Data Packet,
|
|
// defined in the draft of the next version of the OpenPGP specification.
|
|
// If a non-nil AEADConfig is passed, usage of this packet is enabled. By
|
|
// default, it is disabled. See the documentation of AEADConfig for more
|
|
// configuration options related to AEAD.
|
|
// **Note: using this option may break compatibility with other OpenPGP
|
|
// implementations, as well as future versions of this library.**
|
|
AEADConfig *AEADConfig
|
|
// V6Keys configures version 6 key generation. If false, this package still
|
|
// supports version 6 keys, but produces version 4 keys.
|
|
V6Keys bool
|
|
// Minimum RSA key size allowed for key generation and message signing, verification and encryption.
|
|
MinRSABits uint16
|
|
// Reject insecure algorithms, only works with v2 api
|
|
RejectPublicKeyAlgorithms map[PublicKeyAlgorithm]bool
|
|
RejectHashAlgorithms map[crypto.Hash]bool
|
|
RejectMessageHashAlgorithms map[crypto.Hash]bool
|
|
RejectCurves map[Curve]bool
|
|
// "The validity period of the key. This is the number of seconds after
|
|
// the key creation time that the key expires. If this is not present
|
|
// or has a value of zero, the key never expires. This is found only on
|
|
// a self-signature.""
|
|
// https://tools.ietf.org/html/rfc4880#section-5.2.3.6
|
|
KeyLifetimeSecs uint32
|
|
// "The validity period of the signature. This is the number of seconds
|
|
// after the signature creation time that the signature expires. If
|
|
// this is not present or has a value of zero, it never expires."
|
|
// https://tools.ietf.org/html/rfc4880#section-5.2.3.10
|
|
SigLifetimeSecs uint32
|
|
// SigningKeyId is used to specify the signing key to use (by Key ID).
|
|
// By default, the signing key is selected automatically, preferring
|
|
// signing subkeys if available.
|
|
SigningKeyId uint64
|
|
// SigningIdentity is used to specify a user ID (packet Signer's User ID, type 28)
|
|
// when producing a generic certification signature onto an existing user ID.
|
|
// The identity must be present in the signer Entity.
|
|
SigningIdentity string
|
|
// InsecureAllowUnauthenticatedMessages controls, whether it is tolerated to read
|
|
// encrypted messages without Modification Detection Code (MDC).
|
|
// MDC is mandated by the IETF OpenPGP Crypto Refresh draft and has long been implemented
|
|
// in most OpenPGP implementations. Messages without MDC are considered unnecessarily
|
|
// insecure and should be prevented whenever possible.
|
|
// In case one needs to deal with messages from very old OpenPGP implementations, there
|
|
// might be no other way than to tolerate the missing MDC. Setting this flag, allows this
|
|
// mode of operation. It should be considered a measure of last resort.
|
|
InsecureAllowUnauthenticatedMessages bool
|
|
// InsecureAllowDecryptionWithSigningKeys allows decryption with keys marked as signing keys in the v2 API.
|
|
// This setting is potentially insecure, but it is needed as some libraries
|
|
// ignored key flags when selecting a key for encryption.
|
|
// Not relevant for the v1 API, as all keys were allowed in decryption.
|
|
InsecureAllowDecryptionWithSigningKeys bool
|
|
// KnownNotations is a map of Notation Data names to bools, which controls
|
|
// the notation names that are allowed to be present in critical Notation Data
|
|
// signature subpackets.
|
|
KnownNotations map[string]bool
|
|
// SignatureNotations is a list of Notations to be added to any signatures.
|
|
SignatureNotations []*Notation
|
|
// CheckIntendedRecipients controls, whether the OpenPGP Intended Recipient Fingerprint feature
|
|
// should be enabled for encryption and decryption.
|
|
// (See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-intended-recipient-fingerpr).
|
|
// When the flag is set, encryption produces Intended Recipient Fingerprint signature sub-packets and decryption
|
|
// checks whether the key it was encrypted to is one of the included fingerprints in the signature.
|
|
// If the flag is disabled, no Intended Recipient Fingerprint sub-packets are created or checked.
|
|
// The default behavior, when the config or flag is nil, is to enable the feature.
|
|
CheckIntendedRecipients *bool
|
|
// CacheSessionKey controls if decryption should return the session key used for decryption.
|
|
// If the flag is set, the session key is cached in the message details struct.
|
|
CacheSessionKey bool
|
|
// CheckPacketSequence is a flag that controls if the pgp message reader should strictly check
|
|
// that the packet sequence conforms with the grammar mandated by rfc4880.
|
|
// The default behavior, when the config or flag is nil, is to check the packet sequence.
|
|
CheckPacketSequence *bool
|
|
// NonDeterministicSignaturesViaNotation is a flag to enable randomization of signatures.
|
|
// If true, a salt notation is used to randomize signatures generated by v4 and v5 keys
|
|
// (v6 signatures are always non-deterministic, by design).
|
|
// This protects EdDSA signatures from potentially leaking the secret key in case of faults (i.e. bitflips) which, in principle, could occur
|
|
// during the signing computation. It is added to signatures of any algo for simplicity, and as it may also serve as protection in case of
|
|
// weaknesses in the hash algo, potentially hindering e.g. some chosen-prefix attacks.
|
|
// The default behavior, when the config or flag is nil, is to enable the feature.
|
|
NonDeterministicSignaturesViaNotation *bool
|
|
|
|
// InsecureAllowAllKeyFlagsWhenMissing determines how a key without valid key flags is handled.
|
|
// When set to true, a key without flags is treated as if all flags are enabled.
|
|
// This behavior is consistent with GPG.
|
|
InsecureAllowAllKeyFlagsWhenMissing bool
|
|
}
|
|
|
|
func (c *Config) Random() io.Reader {
|
|
if c == nil || c.Rand == nil {
|
|
return rand.Reader
|
|
}
|
|
return c.Rand
|
|
}
|
|
|
|
func (c *Config) Hash() crypto.Hash {
|
|
if c == nil || uint(c.DefaultHash) == 0 {
|
|
return crypto.SHA256
|
|
}
|
|
return c.DefaultHash
|
|
}
|
|
|
|
func (c *Config) Cipher() CipherFunction {
|
|
if c == nil || uint8(c.DefaultCipher) == 0 {
|
|
return CipherAES128
|
|
}
|
|
return c.DefaultCipher
|
|
}
|
|
|
|
func (c *Config) Now() time.Time {
|
|
if c == nil || c.Time == nil {
|
|
return time.Now().Truncate(time.Second)
|
|
}
|
|
return c.Time().Truncate(time.Second)
|
|
}
|
|
|
|
// KeyLifetime returns the validity period of the key.
|
|
func (c *Config) KeyLifetime() uint32 {
|
|
if c == nil {
|
|
return 0
|
|
}
|
|
return c.KeyLifetimeSecs
|
|
}
|
|
|
|
// SigLifetime returns the validity period of the signature.
|
|
func (c *Config) SigLifetime() uint32 {
|
|
if c == nil {
|
|
return 0
|
|
}
|
|
return c.SigLifetimeSecs
|
|
}
|
|
|
|
func (c *Config) Compression() CompressionAlgo {
|
|
if c == nil {
|
|
return CompressionNone
|
|
}
|
|
return c.DefaultCompressionAlgo
|
|
}
|
|
|
|
func (c *Config) RSAModulusBits() int {
|
|
if c == nil || c.RSABits == 0 {
|
|
return 2048
|
|
}
|
|
return c.RSABits
|
|
}
|
|
|
|
func (c *Config) PublicKeyAlgorithm() PublicKeyAlgorithm {
|
|
if c == nil || c.Algorithm == 0 {
|
|
return PubKeyAlgoRSA
|
|
}
|
|
return c.Algorithm
|
|
}
|
|
|
|
func (c *Config) CurveName() Curve {
|
|
if c == nil || c.Curve == "" {
|
|
return Curve25519
|
|
}
|
|
return c.Curve
|
|
}
|
|
|
|
// Deprecated: The hash iterations should now be queried via the S2K() method.
|
|
func (c *Config) PasswordHashIterations() int {
|
|
if c == nil || c.S2KCount == 0 {
|
|
return 0
|
|
}
|
|
return c.S2KCount
|
|
}
|
|
|
|
func (c *Config) S2K() *s2k.Config {
|
|
if c == nil {
|
|
return nil
|
|
}
|
|
// for backwards compatibility
|
|
if c.S2KCount > 0 && c.S2KConfig == nil {
|
|
return &s2k.Config{
|
|
S2KCount: c.S2KCount,
|
|
}
|
|
}
|
|
return c.S2KConfig
|
|
}
|
|
|
|
func (c *Config) AEAD() *AEADConfig {
|
|
if c == nil {
|
|
return nil
|
|
}
|
|
return c.AEADConfig
|
|
}
|
|
|
|
func (c *Config) SigningKey() uint64 {
|
|
if c == nil {
|
|
return 0
|
|
}
|
|
return c.SigningKeyId
|
|
}
|
|
|
|
func (c *Config) SigningUserId() string {
|
|
if c == nil {
|
|
return ""
|
|
}
|
|
return c.SigningIdentity
|
|
}
|
|
|
|
func (c *Config) AllowUnauthenticatedMessages() bool {
|
|
if c == nil {
|
|
return false
|
|
}
|
|
return c.InsecureAllowUnauthenticatedMessages
|
|
}
|
|
|
|
func (c *Config) AllowDecryptionWithSigningKeys() bool {
|
|
if c == nil {
|
|
return false
|
|
}
|
|
return c.InsecureAllowDecryptionWithSigningKeys
|
|
}
|
|
|
|
func (c *Config) KnownNotation(notationName string) bool {
|
|
if c == nil {
|
|
return false
|
|
}
|
|
return c.KnownNotations[notationName]
|
|
}
|
|
|
|
func (c *Config) Notations() []*Notation {
|
|
if c == nil {
|
|
return nil
|
|
}
|
|
return c.SignatureNotations
|
|
}
|
|
|
|
func (c *Config) V6() bool {
|
|
if c == nil {
|
|
return false
|
|
}
|
|
return c.V6Keys
|
|
}
|
|
|
|
func (c *Config) IntendedRecipients() bool {
|
|
if c == nil || c.CheckIntendedRecipients == nil {
|
|
return true
|
|
}
|
|
return *c.CheckIntendedRecipients
|
|
}
|
|
|
|
func (c *Config) RetrieveSessionKey() bool {
|
|
if c == nil {
|
|
return false
|
|
}
|
|
return c.CacheSessionKey
|
|
}
|
|
|
|
func (c *Config) MinimumRSABits() uint16 {
|
|
if c == nil || c.MinRSABits == 0 {
|
|
return 2047
|
|
}
|
|
return c.MinRSABits
|
|
}
|
|
|
|
func (c *Config) RejectPublicKeyAlgorithm(alg PublicKeyAlgorithm) bool {
|
|
var rejectedAlgorithms map[PublicKeyAlgorithm]bool
|
|
if c == nil || c.RejectPublicKeyAlgorithms == nil {
|
|
// Default
|
|
rejectedAlgorithms = defaultRejectPublicKeyAlgorithms
|
|
} else {
|
|
rejectedAlgorithms = c.RejectPublicKeyAlgorithms
|
|
}
|
|
return rejectedAlgorithms[alg]
|
|
}
|
|
|
|
func (c *Config) RejectHashAlgorithm(hash crypto.Hash) bool {
|
|
var rejectedAlgorithms map[crypto.Hash]bool
|
|
if c == nil || c.RejectHashAlgorithms == nil {
|
|
// Default
|
|
rejectedAlgorithms = defaultRejectHashAlgorithms
|
|
} else {
|
|
rejectedAlgorithms = c.RejectHashAlgorithms
|
|
}
|
|
return rejectedAlgorithms[hash]
|
|
}
|
|
|
|
func (c *Config) RejectMessageHashAlgorithm(hash crypto.Hash) bool {
|
|
var rejectedAlgorithms map[crypto.Hash]bool
|
|
if c == nil || c.RejectMessageHashAlgorithms == nil {
|
|
// Default
|
|
rejectedAlgorithms = defaultRejectMessageHashAlgorithms
|
|
} else {
|
|
rejectedAlgorithms = c.RejectMessageHashAlgorithms
|
|
}
|
|
return rejectedAlgorithms[hash]
|
|
}
|
|
|
|
func (c *Config) RejectCurve(curve Curve) bool {
|
|
var rejectedCurve map[Curve]bool
|
|
if c == nil || c.RejectCurves == nil {
|
|
// Default
|
|
rejectedCurve = defaultRejectCurves
|
|
} else {
|
|
rejectedCurve = c.RejectCurves
|
|
}
|
|
return rejectedCurve[curve]
|
|
}
|
|
|
|
func (c *Config) StrictPacketSequence() bool {
|
|
if c == nil || c.CheckPacketSequence == nil {
|
|
return true
|
|
}
|
|
return *c.CheckPacketSequence
|
|
}
|
|
|
|
func (c *Config) RandomizeSignaturesViaNotation() bool {
|
|
if c == nil || c.NonDeterministicSignaturesViaNotation == nil {
|
|
return true
|
|
}
|
|
return *c.NonDeterministicSignaturesViaNotation
|
|
}
|
|
|
|
func (c *Config) AllowAllKeyFlagsWhenMissing() bool {
|
|
if c == nil {
|
|
return false
|
|
}
|
|
return c.InsecureAllowAllKeyFlagsWhenMissing
|
|
}
|
|
|
|
// BoolPointer is a helper function to set a boolean pointer in the Config.
|
|
// e.g., config.CheckPacketSequence = BoolPointer(true)
|
|
func BoolPointer(value bool) *bool {
|
|
return &value
|
|
}
|