WIP: implement openpgp signing
This commit is contained in:
parent
9f0916b14a
commit
c8e6792622
4 changed files with 93 additions and 2 deletions
1
go.mod
1
go.mod
|
@ -5,6 +5,7 @@ go 1.15
|
||||||
require (
|
require (
|
||||||
github.com/sirupsen/logrus v1.7.0
|
github.com/sirupsen/logrus v1.7.0
|
||||||
go.bug.st/serial v1.1.1
|
go.bug.st/serial v1.1.1
|
||||||
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|
7
go.sum
7
go.sum
|
@ -15,9 +15,16 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
go.bug.st/serial v1.1.1 h1:5J1DpaIaSIruBi7jVnKXnhRS+YQ9+2PLJMtIZKoIgnc=
|
go.bug.st/serial v1.1.1 h1:5J1DpaIaSIruBi7jVnKXnhRS+YQ9+2PLJMtIZKoIgnc=
|
||||||
go.bug.st/serial v1.1.1/go.mod h1:VmYBeyJWp5BnJ0tw2NUJHZdJTGl2ecBGABHlzRK1knY=
|
go.bug.st/serial v1.1.1/go.mod h1:VmYBeyJWp5BnJ0tw2NUJHZdJTGl2ecBGABHlzRK1knY=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||||
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM=
|
||||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
|
|
|
@ -2,6 +2,7 @@ package signer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
|
@ -18,6 +19,7 @@ import (
|
||||||
|
|
||||||
"git.cacert.org/cacert-gosigner/datastructures"
|
"git.cacert.org/cacert-gosigner/datastructures"
|
||||||
"git.cacert.org/cacert-gosigner/shared"
|
"git.cacert.org/cacert-gosigner/shared"
|
||||||
|
"git.cacert.org/cacert-gosigner/signer/openpgp_ops"
|
||||||
"git.cacert.org/cacert-gosigner/signer/x509_ops"
|
"git.cacert.org/cacert-gosigner/signer/x509_ops"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -248,7 +250,7 @@ func (p *CommandProcessor) revokeX509(system *IdSystemParameters, request []byte
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("could not generate xdelta: %v", err)
|
log.Warnf("could not generate xdelta: %v", err)
|
||||||
}
|
}
|
||||||
log.Tracef("xdelte produced %d bytes", len(content))
|
log.Tracef("xdelta produced %d bytes", len(content))
|
||||||
}
|
}
|
||||||
if content == nil {
|
if content == nil {
|
||||||
content = pem.EncodeToMemory(&pem.Block{
|
content = pem.EncodeToMemory(&pem.Block{
|
||||||
|
@ -309,7 +311,17 @@ func (p *CommandProcessor) signX509Certificate(system *IdSystemParameters, days
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *CommandProcessor) signOpenpgpKey(system *IdSystemParameters, days uint16, pubKey []byte) ([]byte, error) {
|
func (p *CommandProcessor) signOpenpgpKey(system *IdSystemParameters, days uint16, pubKey []byte) ([]byte, error) {
|
||||||
return nil, errors.New("signOpenpgpKey is not implemented yet")
|
openPgpRoot := system.Root.(*openpgp_ops.OpenPGPRoot)
|
||||||
|
signatureAlgorithm := system.MessageDigestAlgorithm.(*crypto.Hash)
|
||||||
|
|
||||||
|
log.Debugf("sign openpgp for root %s", openPgpRoot)
|
||||||
|
|
||||||
|
content, err := openPgpRoot.SignPublicKey(pubKey, signatureAlgorithm, days)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not sign openpgp public key with root %s: %v", openPgpRoot, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return content, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCommandProcessorSettings() *CommandProcessorSettings {
|
func NewCommandProcessorSettings() *CommandProcessorSettings {
|
||||||
|
|
|
@ -1,11 +1,82 @@
|
||||||
package openpgp_ops
|
package openpgp_ops
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/crypto/openpgp"
|
||||||
|
"golang.org/x/crypto/openpgp/packet"
|
||||||
|
)
|
||||||
|
|
||||||
type OpenPGPRoot struct {
|
type OpenPGPRoot struct {
|
||||||
Name string
|
Name string
|
||||||
SecretKeyRing string
|
SecretKeyRing string
|
||||||
Identifier string
|
Identifier string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *OpenPGPRoot) SignPublicKey(pubKey []byte, algorithm *crypto.Hash, days uint16) ([]byte, error) {
|
||||||
|
signingKey, err := r.findSigningKey(r.Identifier)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not find a signing key matching %s: %v", r.Identifier, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
pubKeyRing, err := openpgp.ReadKeyRing(bytes.NewReader(pubKey))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not read openpgp keyring: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
signatures := make([]*openpgp.Entity, 0)
|
||||||
|
|
||||||
|
for _, pe := range pubKeyRing {
|
||||||
|
log.Tracef("found %+v", pe)
|
||||||
|
for _, i := range pe.Identities {
|
||||||
|
if !i.SelfSignature.KeyExpired(time.Now()) {
|
||||||
|
signConfig := &packet.Config{
|
||||||
|
DefaultHash: *algorithm,
|
||||||
|
Time: func() { return calculateExpiry(i, days) },
|
||||||
|
}
|
||||||
|
pe.SignIdentity(i.Name, signingKey, signConfig)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func calculateExpiry(i *openpgp.Identity, days uint16) time.Time {
|
||||||
|
maxExpiry := i.SelfSignature.CreationTime.Add(time.Second * time.Duration(*i.SelfSignature.KeyLifetimeSecs))
|
||||||
|
calcExpiry := time.Now().Add(time.Hour * 24 * time.Duration(days))
|
||||||
|
|
||||||
|
if calcExpiry.After(maxExpiry) {
|
||||||
|
return maxExpiry
|
||||||
|
}
|
||||||
|
return maxExpiry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *OpenPGPRoot) findSigningKey(identifier string) (*openpgp.Entity, error) {
|
||||||
|
keyring, err := os.Open(r.SecretKeyRing)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not open secret keyring: %v", err)
|
||||||
|
}
|
||||||
|
defer func() { _ = keyring.Close() }()
|
||||||
|
|
||||||
|
el, err := openpgp.ReadKeyRing(keyring)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not read keyring: %v", err)
|
||||||
|
}
|
||||||
|
for _, e := range el {
|
||||||
|
log.Tracef("found %+v", e)
|
||||||
|
for _, i := range e.Identities {
|
||||||
|
if i.UserId.Email == identifier && len(e.Revocations) == 0 && !i.SelfSignature.KeyExpired(time.Now()) {
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("no matching key found")
|
||||||
|
}
|
||||||
|
|
||||||
type OpenPGPProfile struct {
|
type OpenPGPProfile struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue