main.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. package main // import "github.com/cryptix/cmd/scb"
  2. import (
  3. "encoding/base64"
  4. "errors"
  5. "io"
  6. "net"
  7. "os"
  8. "os/user"
  9. "path/filepath"
  10. "strings"
  11. "time"
  12. "cryptoscope.co/go/secretstream"
  13. "cryptoscope.co/go/secretstream/secrethandshake"
  14. "github.com/codegangsta/cli"
  15. "github.com/cryptix/go/logging"
  16. humanize "github.com/dustin/go-humanize"
  17. kitlog "github.com/go-kit/kit/log"
  18. "github.com/miolini/datacounter"
  19. )
  20. var (
  21. sbotAppKey []byte
  22. defaultKeyFile string
  23. log kitlog.Logger
  24. )
  25. func init() {
  26. u, err := user.Current()
  27. logging.CheckFatal(err)
  28. defaultKeyFile = filepath.Join(u.HomeDir, ".ssb", "secret")
  29. }
  30. func main() {
  31. app := cli.NewApp()
  32. app.Name = "scb"
  33. app.Usage = "securly boxes your cats from a to b"
  34. app.Version = "0.1"
  35. app.Action = run
  36. app.Flags = []cli.Flag{
  37. cli.BoolFlag{Name: "listen,l"},
  38. cli.StringFlag{Name: "appKey", Value: "sAI1D9LtA6TQj3qj59/3bdKqiv4QQC3DY6/fWzBTDr8=", Usage: "the shared secret/mac key (in base64, plz)"},
  39. cli.StringFlag{Name: "key,k", Value: defaultKeyFile, Usage: "the ssb keyfile to load the local keypair from"},
  40. }
  41. logging.SetupLogging(nil)
  42. log = logging.Logger(app.Name)
  43. app.Run(os.Args)
  44. }
  45. func run(ctx *cli.Context) error {
  46. localKey, err := secrethandshake.LoadSSBKeyPair(ctx.String("key"))
  47. logging.CheckFatal(err)
  48. sbotAppKey, err = base64.StdEncoding.DecodeString(ctx.String("appKey"))
  49. logging.CheckFatal(err)
  50. var conn net.Conn
  51. if ctx.Bool("listen") {
  52. srv, err := secretstream.NewServer(*localKey, sbotAppKey)
  53. logging.CheckFatal(err)
  54. l, err := srv.Listen("tcp", ctx.Args().Get(0))
  55. logging.CheckFatal(err)
  56. log.Log("event", "listening",
  57. "id", base64.StdEncoding.EncodeToString(localKey.Public[:]),
  58. "addr", l.Addr().String(),
  59. )
  60. conn, err = l.Accept()
  61. logging.CheckFatal(err)
  62. } else {
  63. var remotepub [32]byte
  64. rp, err := base64.StdEncoding.DecodeString(strings.TrimSuffix(ctx.Args().Get(1), ".ed25519"))
  65. logging.CheckFatal(err)
  66. copy(remotepub[:], rp)
  67. c, err := secretstream.NewClient(*localKey, sbotAppKey)
  68. logging.CheckFatal(err)
  69. d, err := c.NewDialer(remotepub)
  70. logging.CheckFatal(err)
  71. conn, err = d("tcp", ctx.Args().Get(0))
  72. logging.CheckFatal(err)
  73. }
  74. start := time.Now()
  75. // showing off a little...
  76. rem := conn.RemoteAddr()
  77. shsAddr, ok := rem.(secretstream.Addr)
  78. if !ok {
  79. logging.CheckFatal(errors.New("could not cast remote address"))
  80. }
  81. log.Log("event", "connection established",
  82. "id", base64.StdEncoding.EncodeToString(shsAddr.PubKey()),
  83. "addr", shsAddr.Addr.String(),
  84. )
  85. var sentCounter, recvdCounter *datacounter.ReaderCounter
  86. go func() {
  87. sentCounter = datacounter.NewReaderCounter(os.Stdin)
  88. _, err := io.Copy(conn, sentCounter)
  89. logging.CheckFatal(err)
  90. conn.Close()
  91. }()
  92. recvdCounter = datacounter.NewReaderCounter(conn)
  93. _, err = io.Copy(os.Stdout, recvdCounter)
  94. log.Log("event", "copy done",
  95. "took", time.Since(start),
  96. "sent", humanize.Bytes(sentCounter.Count()),
  97. "rcvd", humanize.Bytes(recvdCounter.Count()),
  98. )
  99. return err
  100. }