Source File
keys.go
Belonging Package
golang.org/x/crypto/openpgp
package openpgp
import (
)
var PublicKeyType = "PGP PUBLIC KEY BLOCK"
var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
type Entity struct {
PrimaryKey *packet.PublicKey
PrivateKey *packet.PrivateKey
Identities map[string]*Identity // indexed by Identity.Name
Revocations []*packet.Signature
Subkeys []Subkey
}
type Subkey struct {
PublicKey *packet.PublicKey
PrivateKey *packet.PrivateKey
Sig *packet.Signature
}
type Key struct {
Entity *Entity
PublicKey *packet.PublicKey
PrivateKey *packet.PrivateKey
SelfSignature *packet.Signature
}
DecryptionKeys() []Key
}
func ( *Entity) () *Identity {
var *Identity
for , := range .Identities {
if == nil {
=
}
if .SelfSignature.IsPrimaryId != nil && *.SelfSignature.IsPrimaryId {
return
}
}
return
}
var time.Time
for , := range .Subkeys {
if .Sig.FlagsValid &&
.Sig.FlagEncryptCommunications &&
.PublicKey.PubKeyAlgo.CanEncrypt() &&
!.Sig.KeyExpired() &&
(.IsZero() || .Sig.CreationTime.After()) {
=
= .Sig.CreationTime
}
}
if != -1 {
:= .Subkeys[]
return Key{, .PublicKey, .PrivateKey, .Sig}, true
}
:= .primaryIdentity()
if !.SelfSignature.FlagsValid || .SelfSignature.FlagEncryptCommunications &&
.PrimaryKey.PubKeyAlgo.CanEncrypt() &&
!.SelfSignature.KeyExpired() {
return Key{, .PrimaryKey, .PrivateKey, .SelfSignature}, true
}
:= .primaryIdentity()
if !.SelfSignature.FlagsValid || .SelfSignature.FlagSign &&
!.SelfSignature.KeyExpired() {
return Key{, .PrimaryKey, .PrivateKey, .SelfSignature}, true
}
return Key{}, false
}
type EntityList []*Entity
func ( EntityList) ( uint64) ( []Key) {
for , := range {
if .PrimaryKey.KeyId == {
var *packet.Signature
for , := range .Identities {
if == nil {
= .SelfSignature
} else if .SelfSignature.IsPrimaryId != nil && *.SelfSignature.IsPrimaryId {
= .SelfSignature
break
}
}
= append(, Key{, .PrimaryKey, .PrivateKey, })
}
for , := range .Subkeys {
if .PublicKey.KeyId == {
= append(, Key{, .PublicKey, .PrivateKey, .Sig})
}
}
}
return
}
func ( EntityList) ( uint64, byte) ( []Key) {
for , := range .KeysById() {
if len(.Entity.Revocations) > 0 {
continue
}
if .SelfSignature.RevocationReason != nil {
continue
}
if .SelfSignature.FlagsValid && != 0 {
var byte
if .SelfSignature.FlagCertify {
|= packet.KeyFlagCertify
}
if .SelfSignature.FlagSign {
|= packet.KeyFlagSign
}
if .SelfSignature.FlagEncryptCommunications {
|= packet.KeyFlagEncryptCommunications
}
if .SelfSignature.FlagEncryptStorage {
|= packet.KeyFlagEncryptStorage
}
if & != {
continue
}
}
= append(, )
}
return
}
func ( EntityList) () ( []Key) {
for , := range {
for , := range .Subkeys {
if .PrivateKey != nil && (!.Sig.FlagsValid || .Sig.FlagEncryptStorage || .Sig.FlagEncryptCommunications) {
= append(, Key{, .PublicKey, .PrivateKey, .Sig})
}
}
}
return
}
func ( io.Reader) (EntityList, error) {
, := armor.Decode()
if == io.EOF {
return nil, errors.InvalidArgumentError("no armored data found")
}
if != nil {
return nil,
}
if .Type != PublicKeyType && .Type != PrivateKeyType {
return nil, errors.InvalidArgumentError("expected public or private key block, got: " + .Type)
}
return ReadKeyRing(.Body)
}
func ( io.Reader) ( EntityList, error) {
:= packet.NewReader()
var error
for {
var *Entity
, = ReadEntity()
if , := .(errors.UnsupportedError); {
=
= readToNextPublicKey()
func ( *packet.Reader) (*Entity, error) {
:= new(Entity)
.Identities = make(map[string]*Identity)
, := .Next()
if != nil {
return nil,
}
var bool
if .PrimaryKey, = .(*packet.PublicKey); ! {
if .PrivateKey, = .(*packet.PrivateKey); ! {
.Unread()
return nil, errors.StructuralError("first packet was not a public/private key")
}
.PrimaryKey = &.PrivateKey.PublicKey
}
if !.PrimaryKey.PubKeyAlgo.CanSign() {
return nil, errors.StructuralError("primary key cannot be used for signatures")
}
var []*packet.Signature
:
for {
, := .Next()
if == io.EOF {
break
} else if != nil {
return nil,
}
switch pkt := .(type) {
case *packet.UserId:
if := addUserID(, , ); != nil {
return nil,
}
case *packet.Signature:
if .SigType == packet.SigTypeKeyRevocation {
= append(, )
}
}
if len(.Identities) == 0 {
return nil, errors.StructuralError("entity without any identities")
}
for , := range {
= .PrimaryKey.VerifyRevocationSignature()
if == nil {
.Revocations = append(.Revocations, )
return nil, errors.StructuralError("revocation signature signed by alternate key")
}
}
return , nil
}
:= new(Identity)
.Name = .Id
.UserId =
for {
, := .Next()
if == io.EOF {
break
} else if != nil {
return
}
, := .(*packet.Signature)
if ! {
.Unread()
break
}
if (.SigType == packet.SigTypePositiveCert || .SigType == packet.SigTypeGenericCert) && .IssuerKeyId != nil && *.IssuerKeyId == .PrimaryKey.KeyId {
if = .PrimaryKey.VerifyUserIdSignature(.Id, .PrimaryKey, ); != nil {
return errors.StructuralError("user ID self-signature invalid: " + .Error())
}
.SelfSignature =
.Identities[.Id] =
} else {
.Signatures = append(.Signatures, )
}
}
return nil
}
func ( *Entity, *packet.Reader, *packet.PublicKey, *packet.PrivateKey) error {
var Subkey
.PublicKey =
.PrivateKey =
for {
, := .Next()
if == io.EOF {
break
} else if != nil {
return errors.StructuralError("subkey signature invalid: " + .Error())
}
, := .(*packet.Signature)
if ! {
.Unread()
break
}
if .SigType != packet.SigTypeSubkeyBinding && .SigType != packet.SigTypeSubkeyRevocation {
return errors.StructuralError("subkey signature with wrong type")
}
if := .PrimaryKey.VerifyKeySignature(.PublicKey, ); != nil {
return errors.StructuralError("subkey signature invalid: " + .Error())
}
switch .SigType {
case packet.SigTypeSubkeyRevocation:
.Sig =
case packet.SigTypeSubkeyBinding:
if shouldReplaceSubkeySig(.Sig, ) {
.Sig =
}
}
}
if .Sig == nil {
return errors.StructuralError("subkey packet not followed by signature")
}
.Subkeys = append(.Subkeys, )
return nil
}
func (, *packet.Signature) bool {
if == nil {
return false
}
if == nil {
return true
}
if .SigType == packet.SigTypeSubkeyRevocation {
return false // never override a revocation signature
}
return .CreationTime.After(.CreationTime)
}
const defaultRSAKeyBits = 2048
func (, , string, *packet.Config) (*Entity, error) {
:= .Now()
:= defaultRSAKeyBits
if != nil && .RSABits != 0 {
= .RSABits
}
:= packet.NewUserId(, , )
if == nil {
return nil, errors.InvalidArgumentError("user id field contained invalid characters")
}
, := rsa.GenerateKey(.Random(), )
if != nil {
return nil,
}
, := rsa.GenerateKey(.Random(), )
if != nil {
return nil,
}
:= &Entity{
PrimaryKey: packet.NewRSAPublicKey(, &.PublicKey),
PrivateKey: packet.NewRSAPrivateKey(, ),
Identities: make(map[string]*Identity),
}
:= true
.Identities[.Id] = &Identity{
Name: .Id,
UserId: ,
SelfSignature: &packet.Signature{
CreationTime: ,
SigType: packet.SigTypePositiveCert,
PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: .Hash(),
IsPrimaryId: &,
FlagsValid: true,
FlagSign: true,
FlagCertify: true,
IssuerKeyId: &.PrimaryKey.KeyId,
},
}
= .Identities[.Id].SelfSignature.SignUserId(.Id, .PrimaryKey, .PrivateKey, )
if != nil {
return nil,
}
if != nil && .DefaultHash != 0 {
.Identities[.Id].SelfSignature.PreferredHash = []uint8{hashToHashId(.DefaultHash)}
}
if != nil && .DefaultCipher != 0 {
.Identities[.Id].SelfSignature.PreferredSymmetric = []uint8{uint8(.DefaultCipher)}
}
.Subkeys = make([]Subkey, 1)
.Subkeys[0] = Subkey{
PublicKey: packet.NewRSAPublicKey(, &.PublicKey),
PrivateKey: packet.NewRSAPrivateKey(, ),
Sig: &packet.Signature{
CreationTime: ,
SigType: packet.SigTypeSubkeyBinding,
PubKeyAlgo: packet.PubKeyAlgoRSA,
Hash: .Hash(),
FlagsValid: true,
FlagEncryptStorage: true,
FlagEncryptCommunications: true,
IssuerKeyId: &.PrimaryKey.KeyId,
},
}
.Subkeys[0].PublicKey.IsSubkey = true
.Subkeys[0].PrivateKey.IsSubkey = true
= .Subkeys[0].Sig.SignKey(.Subkeys[0].PublicKey, .PrivateKey, )
if != nil {
return nil,
}
return , nil
}
func ( *Entity) ( io.Writer, *packet.Config) ( error) {
= .PrivateKey.Serialize()
if != nil {
return
}
for , := range .Identities {
= .UserId.Serialize()
if != nil {
return
}
= .SelfSignature.SignUserId(.UserId.Id, .PrimaryKey, .PrivateKey, )
if != nil {
return
}
= .SelfSignature.Serialize()
if != nil {
return
}
}
for , := range .Subkeys {
= .PrivateKey.Serialize()
if != nil {
return
}
= .Sig.SignKey(.PublicKey, .PrivateKey, )
if != nil {
return
}
= .Sig.Serialize()
if != nil {
return
}
}
return nil
}
func ( *Entity) ( io.Writer) error {
:= .PrimaryKey.Serialize()
if != nil {
return
}
for , := range .Identities {
= .UserId.Serialize()
if != nil {
return
}
= .SelfSignature.Serialize()
if != nil {
return
}
for , := range .Signatures {
= .Serialize()
if != nil {
return
}
}
}
for , := range .Subkeys {
= .PublicKey.Serialize()
if != nil {
return
}
= .Sig.Serialize()
if != nil {
return
}
}
return nil
}
func ( *Entity) ( string, *Entity, *packet.Config) error {
if .PrivateKey == nil {
return errors.InvalidArgumentError("signing Entity must have a private key")
}
if .PrivateKey.Encrypted {
return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
}
, := .Identities[]
if ! {
return errors.InvalidArgumentError("given identity string not found in Entity")
}
:= &packet.Signature{
SigType: packet.SigTypeGenericCert,
PubKeyAlgo: .PrivateKey.PubKeyAlgo,
Hash: .Hash(),
CreationTime: .Now(),
IssuerKeyId: &.PrivateKey.KeyId,
}
if := .SignUserId(, .PrimaryKey, .PrivateKey, ); != nil {
return
}
.Signatures = append(.Signatures, )
return nil
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |