github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/sign.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package libkb 5 6 import ( 7 "bytes" 8 "crypto/sha256" 9 "hash" 10 "io" 11 12 keybase1 "github.com/keybase/client/go/protocol/keybase1" 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 // SimpleSign signs the given data stream, outputs an armored string which is 19 // the attached signature of the input data 20 func SimpleSign(payload []byte, key PGPKeyBundle) (out string, id keybase1.SigIDBase, err error) { 21 var outb bytes.Buffer 22 var in io.WriteCloser 23 var h HashSummer 24 if !key.HasSecretKey() { 25 err = NoSecretKeyError{} 26 return 27 } 28 if in, h, err = ArmoredAttachedSign(NopWriteCloser{&outb}, *key.Entity, nil, nil); err != nil { 29 return 30 } 31 if _, err = in.Write(payload); err != nil { 32 return 33 } 34 if err = in.Close(); err != nil { 35 return 36 } 37 out = outb.String() 38 if id, err = keybase1.SigIDBaseFromSlice(h()); err != nil { 39 return 40 } 41 return 42 } 43 44 type HashingWriteCloser struct { 45 targ io.WriteCloser 46 hasher hash.Hash 47 } 48 49 func (h HashingWriteCloser) Write(buf []byte) (int, error) { 50 n, err := h.targ.Write(buf) 51 if err == nil { 52 _, err = h.hasher.Write(buf) 53 } 54 return n, err 55 } 56 57 func (h HashingWriteCloser) Close() error { 58 err := h.targ.Close() 59 return err 60 } 61 62 type HashSummer func() []byte 63 64 func ArmoredAttachedSign(out io.WriteCloser, signed openpgp.Entity, hints *openpgp.FileHints, config *packet.Config) (in io.WriteCloser, h HashSummer, err error) { 65 66 var aout io.WriteCloser 67 68 aout, err = armor.Encode(out, "PGP MESSAGE", PGPArmorHeaders) 69 if err != nil { 70 return 71 } 72 73 hwc := HashingWriteCloser{aout, sha256.New()} 74 in, err = openpgp.AttachedSign(hwc, signed, hints, config) 75 h = func() []byte { return hwc.hasher.Sum(nil) } 76 77 return in, h, err 78 } 79 80 func AttachedSignWrapper(out io.WriteCloser, key PGPKeyBundle, armored bool) ( 81 in io.WriteCloser, err error) { 82 83 if armored { 84 in, _, err = ArmoredAttachedSign(out, *key.Entity, nil, nil) 85 } else { 86 in, err = openpgp.AttachedSign(out, *key.Entity, nil, nil) 87 } 88 return 89 } 90 91 // NopWriteCloser is like an io.NopCloser, but for an io.Writer. 92 // TODO: we have two of these in OpenPGP packages alone. This probably needs 93 // to be promoted somewhere more common. 94 // 95 // From here: 96 // 97 // https://code.google.com/p/go/source/browse/openpgp/write.go?repo=crypto&r=1e7a3e301825bf9cb32e0535f3761d62d2d369d1#364 98 type NopWriteCloser struct { 99 W io.Writer 100 } 101 102 func (c NopWriteCloser) Write(data []byte) (n int, err error) { 103 return c.W.Write(data) 104 } 105 106 func (c NopWriteCloser) Close() error { 107 return nil 108 }