github.com/code-to-go/safepool.lib@v0.0.0-20221205180519-ee25e63c226e/security/sign.go.bk (about) 1 package security 2 3 import ( 4 "crypto/ed25519" 5 "crypto/rand" 6 "encoding/binary" 7 "io" 8 "github.com/code-to-go/safepool.lib/core" 9 "github.com/code-to-go/safepool.lib/protocol" 10 11 "github.com/golang/protobuf/proto" 12 ) 13 14 type PublicKey ed25519.PublicKey 15 type PrivateKey ed25519.PrivateKey 16 17 const ( 18 PublicKeySize = ed25519.PublicKeySize 19 PrivateKeySize = ed25519.PrivateKeySize 20 SignatureSize = ed25519.SignatureSize 21 ) 22 23 type SignedData struct { 24 Signature [SignatureSize]byte 25 Signer PublicKey 26 } 27 28 type Public struct { 29 Id PublicKey 30 Nick string 31 Email string 32 } 33 34 func NewIdentity() (model.Identity, error) { 35 public, private, err := ed25519.GenerateKey(rand.Reader) 36 if core.IsErr(err, "cannot generate ed25519 identity: %v") { 37 return model.Identity{}, err 38 } 39 40 return model.Identity{ 41 Curve: "ed25519", 42 Public: PublicKey(public), 43 Private: PrivateKey(private), 44 }, nil 45 } 46 47 func Sign(private PrivateKey, data []byte) ([]byte, error) { 48 return ed25519.Sign(ed25519.PrivateKey(private), data), nil 49 } 50 51 func Verify(key PublicKey, data []byte, sig []byte) bool { 52 return ed25519.Verify(ed25519.PublicKey(key), data, sig) 53 } 54 55 func SignAndWrite(private PrivateKey, data []byte, w io.Writer, signatures [][]byte) error { 56 sign, err := Sign(private, data) 57 if core.IsErr(err, "cannot sign data: %v") { 58 return err 59 } 60 signedData := protocol.SignedData{ 61 Version: 1, 62 Data: data, 63 } 64 65 for _, s := range signatures { 66 signedData.Signatures = append(signedData.Signatures, s) 67 } 68 signedData.Signatures = append(signedData.Signatures, sign) 69 70 signedDataB, err := proto.Marshal(&signedData) 71 if core.IsErr(err, "cannot marshal signed data: %v") { 72 return err 73 } 74 75 lenB := make([]byte, 4) 76 binary.BigEndian.PutUint32(lenB, uint32(len(signedDataB))) 77 w.Write(lenB) 78 _, err = w.Write(signedDataB) 79 if core.IsErr(err, "cannot write signed data to stream: %v") { 80 return err 81 } 82 return nil 83 } 84 85 func ReadAndVerify(publics []PublicKey, r io.Reader) (data []byte, signatures [][]byte, err error) { 86 lenB := make([]byte, 4) 87 _, err = r.Read(lenB) 88 if core.IsErr(err, "cannot read length of data") { 89 return nil, nil, err 90 } 91 92 data = make([]byte, binary.BigEndian.Uint32(lenB)) 93 _, err = r.Read(data) 94 if core.IsErr(err, "cannot read signed data") { 95 return nil, nil, err 96 } 97 98 var signedData protocol.SignedData 99 err = proto.Unmarshal(data, &signedData) 100 if core.IsErr(err, "cannot unmarshall signed data: %v") { 101 return nil, nil, err 102 } 103 104 if signedData.Version >= 2.0 { 105 return nil, nil, core.ErrInvalidVersion 106 } 107 108 verified := false 109 out: 110 for _, s := range signedData.Signatures { 111 for _, p := range publics { 112 if Verify(p, signedData.Data, s) { 113 verified = true 114 break out 115 } 116 } 117 } 118 119 if verified { 120 return signedData.Data, signedData.Signatures, nil 121 } else { 122 return nil, nil, core.ErrInvalidSignature 123 } 124 }