aboutsummaryrefslogblamecommitdiff
path: root/sign_input.go
blob: c1ab9e0caa721836d3e23382e61a7cc47b39000f (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11





                 
                   



          
             







                                                
                                                       

                                                                          
                                                     


                                                            
                                                                        




                                   


                                                                     








                                                                                         








                                                                                                   









                                                                                        
                                                                                                                               
                                                                    

                                                                                                               





                                                   








                                                     



                                                                                           







                                                       





                                                                                   

            
package main

import (
  "crypto"
  "crypto/rand"
  "crypto/sha256"
  "encoding/base64"
  "errors"
  "flag"
  "fmt"
  "io"
  "io/ioutil"
  "os"
//  "crypto/ecdsa"
//  "crypto/rsa"
)

type (
  SignInputFlags struct {
    Message        string // the message to sign
    MessageStream  string // the message stream to sign
    PrivateKeyPath string // path to the private key
    Output         string // a path or stream to output the private key to
    Format         string // the format of the output

    private_key crypto.Signer
    output_stream io.Writer // the output stream for the CSR
    input_stream  io.Reader // the input stream to read the message from
  }
)

func sign_input() {
  flags := parse_sign_input_flags()
  if flags.Message != "" && flags.MessageStream != "" {
    crash_with_help(2, "Only message or message file can be signed!")
  }
  flags.private_key = load_private_key(flags.PrivateKeyPath)

  output_stream, err := open_output_stream(flags.Output)
  if err != nil {
    crash_with_help(2, fmt.Sprintf("Error when creating file %s: %s", flags.Output, err))
  }
  flags.output_stream = output_stream
  defer output_stream.Close()

  if flags.MessageStream != "" {
    input_stream, err := open_input_stream(flags.MessageStream)
    if err != nil {
      crash_with_help(2, fmt.Sprintf("Error when opening stream %s: %s", flags.MessageStream, err))
    }
    flags.input_stream = input_stream
    defer input_stream.Close()
  }

  if err := create_signature(flags); err != nil {
    fmt.Fprintln(os.Stderr, "Error when creating signature", err)
    os.Exit(3)
  }
}

func parse_sign_input_flags() SignInputFlags {
  flags := SignInputFlags{}
  fs := flag.NewFlagSet("sign-input", flag.ExitOnError)
  fs.StringVar(&flags.PrivateKeyPath, "private-key", "", "path to the private key file")
  fs.StringVar(&flags.Output, "output", "STDOUT", "path where the generated signature should be stored (STDOUT, STDERR, file)")
  fs.StringVar(&flags.Message, "message", "", "the message to sign")
  fs.StringVar(&flags.MessageStream, "message-stream", "STDIN", "the path to the stream to sign (file, STDIN)")
  fs.StringVar(&flags.Format, "format", "base64", "the output format (binary, base64)")
  fs.Parse(os.Args[2:])

  return flags
}

func create_signature(flags SignInputFlags) error {
  var message []byte
  var err error

  if flags.MessageStream != "" {
    message, err = ioutil.ReadAll(flags.input_stream)
    if err != nil { return err }
  } else {
    message = []byte(flags.Message)
  }
  // compute sha256 of the message
  hash := sha256.New()
  length, _ := hash.Write(message)
  if length != len(message) { return errors.New("Error when creating hash over message!") }

  // create signature of the hash using the private key
  signature, err := flags.private_key.Sign(
    rand.Reader,
    hash.Sum([]byte("")),
    nil,
  )
  if err != nil { return err }
  if flags.Format == "base64" {
    flags.output_stream.Write([]byte(base64.StdEncoding.EncodeToString(signature)))
  } else {
    flags.output_stream.Write(signature)
  }
  flags.output_stream.Write([]byte("\n"))
  return nil
}