Skip to content

Commit

Permalink
feat: factor out the touch notification for gpg signing too
Browse files Browse the repository at this point in the history
  • Loading branch information
smlx committed Jul 26, 2021
1 parent 7c29bd0 commit 8c25037
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 24 deletions.
12 changes: 8 additions & 4 deletions internal/assuan/assuan.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

"github.com/smlx/fsm"
"github.com/smlx/piv-agent/internal/gpg"
"github.com/smlx/piv-agent/internal/notify"
"github.com/smlx/piv-agent/internal/pivservice"
"golang.org/x/crypto/cryptobyte"
"golang.org/x/crypto/cryptobyte/asn1"
Expand Down Expand Up @@ -260,11 +261,14 @@ func hexDecode(data ...[]byte) ([][]byte, error) {
// sign performs signing of the specified "hash" data, using the specified
// "hashAlgo" hash algorithm. It then encodes the response into an s-expression
// and returns it as a byte slice.
//
// This function's complexity is due to the fact that while Sign() returns the
// r and s components of the signature ASN1-encoded, gpg expects them to be
// separately s-exp encoded. So we have to decode the ASN1 signature, extract
// the params, and re-encode them into the s-exp. Ugh.
func (a *Assuan) sign() ([]byte, error) {
// This function's complexity is due to the fact that while Sign() returns
// the r and s components of the signature ASN1-encoded, gpg expects them to
// be separately s-exp encoded. So we have to decode the ASN1 signature,
// extract the params, and re-encode them into the s-exp. Ugh.
cancel := notify.Touch(nil)
defer cancel()
signature, err := a.signingPrivKey.Sign(rand.Reader, a.hash, a.hashAlgo)
if err != nil {
return nil, fmt.Errorf("couldn't sign: %v", err)
Expand Down
31 changes: 31 additions & 0 deletions internal/notify/touch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package notify

import (
"context"
"time"

"github.com/gen2brain/beeep"
"go.uber.org/zap"
)

const waitTime = 6 * time.Second

// Touch starts a goroutine, and waits for a short period. If the returned
// CancelFunc has not been called it sends a notification to remind the user to
// physically touch the Security Key.
func Touch(log *zap.Logger) context.CancelFunc {
ctx, cancel := context.WithCancel(context.Background())
timer := time.NewTimer(waitTime)
go func() {
select {
case <-ctx.Done():
timer.Stop()
case <-timer.C:
err := beeep.Alert("Security Key Agent", "Waiting for touch...", "")
if err != nil && log != nil {
log.Warn("couldn't send touch notification", zap.Error(err))
}
}
}()
return cancel
}
22 changes: 2 additions & 20 deletions internal/ssh/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@ package ssh

import (
"bytes"
"context"
"crypto/rand"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sync"
"time"

"github.com/gen2brain/beeep"
"github.com/smlx/piv-agent/internal/notify"
pinentry "github.com/smlx/piv-agent/internal/pinentry"
"github.com/smlx/piv-agent/internal/pivservice"
"go.uber.org/zap"
Expand Down Expand Up @@ -146,9 +144,8 @@ func (a *Agent) signWithSigners(key gossh.PublicKey, data []byte, signers []goss
continue
}
// (possibly) send a notification
ctx, cancel := context.WithCancel(context.Background())
cancel := notify.Touch(a.log)
defer cancel()
a.touchNotify(ctx)
// perform signature
a.log.Debug("signing",
zap.Binary("public key bytes", s.PublicKey().Marshal()))
Expand All @@ -157,21 +154,6 @@ func (a *Agent) signWithSigners(key gossh.PublicKey, data []byte, signers []goss
return nil, fmt.Errorf("%w: %v", ErrUnknownKey, key)
}

func (a *Agent) touchNotify(ctx context.Context) {
timer := time.NewTimer(8 * time.Second)
go func() {
select {
case <-ctx.Done():
timer.Stop()
case <-timer.C:
err := beeep.Alert("Security Key Agent", "Waiting for touch...", "")
if err != nil {
a.log.Warn("couldn't send touch notification", zap.Error(err))
}
}
}()
}

// Add adds a private key to the agent.
func (a *Agent) Add(key agent.AddedKey) error {
return ErrNotImplemented
Expand Down

0 comments on commit 8c25037

Please sign in to comment.