code.gitea.io/gitea@v1.22.3/models/asymkey/gpg_key_common.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package asymkey 5 6 import ( 7 "bytes" 8 "crypto" 9 "encoding/base64" 10 "fmt" 11 "hash" 12 "io" 13 "strings" 14 "time" 15 16 "github.com/keybase/go-crypto/openpgp" 17 "github.com/keybase/go-crypto/openpgp/armor" 18 "github.com/keybase/go-crypto/openpgp/packet" 19 ) 20 21 // __________________ ________ ____ __. 22 // / _____/\______ \/ _____/ | |/ _|____ ___.__. 23 // / \ ___ | ___/ \ ___ | <_/ __ < | | 24 // \ \_\ \| | \ \_\ \ | | \ ___/\___ | 25 // \______ /|____| \______ / |____|__ \___ > ____| 26 // \/ \/ \/ \/\/ 27 // _________ 28 // \_ ___ \ ____ _____ _____ ____ ____ 29 // / \ \/ / _ \ / \ / \ / _ \ / \ 30 // \ \___( <_> ) Y Y \ Y Y ( <_> ) | \ 31 // \______ /\____/|__|_| /__|_| /\____/|___| / 32 // \/ \/ \/ \/ 33 34 // This file provides common functions relating to GPG Keys 35 36 // checkArmoredGPGKeyString checks if the given key string is a valid GPG armored key. 37 // The function returns the actual public key on success 38 func checkArmoredGPGKeyString(content string) (openpgp.EntityList, error) { 39 list, err := openpgp.ReadArmoredKeyRing(strings.NewReader(content)) 40 if err != nil { 41 return nil, ErrGPGKeyParsing{err} 42 } 43 return list, nil 44 } 45 46 // base64EncPubKey encode public key content to base 64 47 func base64EncPubKey(pubkey *packet.PublicKey) (string, error) { 48 var w bytes.Buffer 49 err := pubkey.Serialize(&w) 50 if err != nil { 51 return "", err 52 } 53 return base64.StdEncoding.EncodeToString(w.Bytes()), nil 54 } 55 56 func readerFromBase64(s string) (io.Reader, error) { 57 bs, err := base64.StdEncoding.DecodeString(s) 58 if err != nil { 59 return nil, err 60 } 61 return bytes.NewBuffer(bs), nil 62 } 63 64 // base64DecPubKey decode public key content from base 64 65 func base64DecPubKey(content string) (*packet.PublicKey, error) { 66 b, err := readerFromBase64(content) 67 if err != nil { 68 return nil, err 69 } 70 // Read key 71 p, err := packet.Read(b) 72 if err != nil { 73 return nil, err 74 } 75 // Check type 76 pkey, ok := p.(*packet.PublicKey) 77 if !ok { 78 return nil, fmt.Errorf("key is not a public key") 79 } 80 return pkey, nil 81 } 82 83 // getExpiryTime extract the expire time of primary key based on sig 84 func getExpiryTime(e *openpgp.Entity) time.Time { 85 expiry := time.Time{} 86 // Extract self-sign for expire date based on : https://github.com/golang/crypto/blob/master/openpgp/keys.go#L165 87 var selfSig *packet.Signature 88 for _, ident := range e.Identities { 89 if selfSig == nil { 90 selfSig = ident.SelfSignature 91 } else if ident.SelfSignature.IsPrimaryId != nil && *ident.SelfSignature.IsPrimaryId { 92 selfSig = ident.SelfSignature 93 break 94 } 95 } 96 if selfSig.KeyLifetimeSecs != nil { 97 expiry = e.PrimaryKey.CreationTime.Add(time.Duration(*selfSig.KeyLifetimeSecs) * time.Second) 98 } 99 return expiry 100 } 101 102 func populateHash(hashFunc crypto.Hash, msg []byte) (hash.Hash, error) { 103 h := hashFunc.New() 104 if _, err := h.Write(msg); err != nil { 105 return nil, err 106 } 107 return h, nil 108 } 109 110 // readArmoredSign read an armored signature block with the given type. https://sourcegraph.com/github.com/golang/crypto/-/blob/openpgp/read.go#L24:6-24:17 111 func readArmoredSign(r io.Reader) (body io.Reader, err error) { 112 block, err := armor.Decode(r) 113 if err != nil { 114 return nil, err 115 } 116 if block.Type != openpgp.SignatureType { 117 return nil, fmt.Errorf("expected '" + openpgp.SignatureType + "', got: " + block.Type) 118 } 119 return block.Body, nil 120 } 121 122 func extractSignature(s string) (*packet.Signature, error) { 123 r, err := readArmoredSign(strings.NewReader(s)) 124 if err != nil { 125 return nil, fmt.Errorf("Failed to read signature armor") 126 } 127 p, err := packet.Read(r) 128 if err != nil { 129 return nil, fmt.Errorf("Failed to read signature packet") 130 } 131 sig, ok := p.(*packet.Signature) 132 if !ok { 133 return nil, fmt.Errorf("Packet is not a signature") 134 } 135 return sig, nil 136 } 137 138 func tryGetKeyIDFromSignature(sig *packet.Signature) string { 139 if sig.IssuerKeyId != nil && (*sig.IssuerKeyId) != 0 { 140 return fmt.Sprintf("%016X", *sig.IssuerKeyId) 141 } 142 if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) > 0 { 143 return fmt.Sprintf("%016X", sig.IssuerFingerprint[12:20]) 144 } 145 return "" 146 }