diff --git a/cmd/taler-auditor-offline-signing/main.go b/cmd/taler-auditor-offline-signing/main.go index 2f192c7..92db7b2 100644 --- a/cmd/taler-auditor-offline-signing/main.go +++ b/cmd/taler-auditor-offline-signing/main.go @@ -5,11 +5,12 @@ https://git.taler.net/exchange.git/tree/src/exchange-tools/taler-auditor-offline in order to simplify portability (to ARM f.e.). TODOs: - - implement sign operation - - implement JSON-encoding of - - hashes - - keys - - signatures + - [ ] implement TALER_exchange_offline_denom_validity_verify + - [ ] implement TALER_auditor_denom_validity_sign + - [x] implement JSON-encoding of + - [x] hashes + - [x] keys + - [x] signatures - factor out types and helper functions to own package codeblau.de/taler - implement full functionality from origin @@ -20,9 +21,12 @@ import ( "bytes" "crypto/ed25519" "crypto/rsa" + "crypto/sha512" "encoding/binary" "encoding/json" + "flag" "fmt" + "io/ioutil" "log" "math/big" "os" @@ -355,19 +359,23 @@ func (ep *RSAPublicKey) UnmarshalJSON(in []byte) (e error) { return nil } -func (ep *RSAPublicKey) MarshalJSON() (b []byte, e error) { +func (ep *RSAPublicKey) Binary() []byte { nb := ep.N.Bytes() eb := big.NewInt(int64(ep.E)).Bytes() if len(nb) > 2<<16-1 || len(eb) > 2<<16-1 { - return nil, fmt.Errorf("values too large") + panic("values too large") } - buf := make([]byte, 4+len(nb)+len(eb)) binary.BigEndian.PutUint16(buf, uint16(len(nb))) binary.BigEndian.PutUint16(buf[2:], uint16(len(eb))) copy(buf[4:], nb) copy(buf[4+len(nb):], eb) + return buf +} +func (ep *RSAPublicKey) MarshalJSON() (b []byte, e error) { + + buf := ep.Binary() enc, err := crockfordEncode(buf) if err != nil { return nil, err @@ -386,22 +394,69 @@ type Output []SignOperation type SignOperation struct { Operation string `json:"operation"` Arguments struct { - HDenumPub RSAPublicKey `json:"h_denum_pub"` + HDenumPub SHA512Hash `json:"h_denum_pub"` AuditorSig EdDSASignature `json:"auditor_sig"` } `json:"arguments"` } +type SHA512Hash []byte + +func (h *SHA512Hash) MarshalJSON() ([]byte, error) { + enc, err := crockfordEncode(*h) + if err != nil { + return nil, fmt.Errorf("error encoding %v: %e\n", h, err) + } + + b := make([]byte, len(enc)+2) + b[0] = '"' + b[len(b)-1] = '"' + copy(b[1:], enc) + + return b, nil +} + +var keyfile = flag.String("key", "", "filename of EC25519 private key") + func main() { + + flag.Parse() + + if len(*keyfile) == 0 { + log.Println("keyfile needed") + return + } + + k, e := ioutil.ReadFile(*keyfile) + if e != nil { + log.Printf("couldn't read keyfile: %v\n", e) + return + } + pk := ed25519.NewKeyFromSeed(k) + input := new(Input) dec := json.NewDecoder(os.Stdin) - e := dec.Decode(input) + e = dec.Decode(input) if e != nil { log.Fatal(e) } + // TODO: here needs to go the call to TALER_exchange_offline_denom_validity_verify + + output := make([]SignOperation, len(input.Arguments.Denoms)) + for i, denom := range input.Arguments.Denoms { + output[i].Operation = "auditor-sign-denomination-0" + bin := denom.DenomPub.Binary() + sum := sha512.Sum512(bin) + output[i].Arguments.HDenumPub = sum[:] + + // TODO: here needs to go the call to TALER_auditor_denom_validity_sign + sig := ed25519.Sign(pk, sum[:]) + output[i].Arguments.AuditorSig = EdDSASignature{R: sig[:32], S: sig[32:]} + } + enc := json.NewEncoder(os.Stdout) - enc.SetIndent("Input:", " ") - e = enc.Encode(input) + enc.SetIndent("", " ") + e = enc.Encode(output) if e != nil { log.Fatal(e) }