You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

gpg_key_common.go 3.8KB

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