diff --git a/cmd/taler-auditor-offline-signing/main.go b/cmd/taler-auditor-offline-signing/main.go index dfbfd0c..6662f44 100644 --- a/cmd/taler-auditor-offline-signing/main.go +++ b/cmd/taler-auditor-offline-signing/main.go @@ -5,14 +5,15 @@ https://git.taler.net/exchange.git/tree/src/exchange-tools/taler-auditor-offline in order to simplify portability (to ARM f.e.). TODOs: - - [ ] implement TALER_exchange_offline_denom_validity_verify - - [ ] implement TALER_auditor_denom_validity_sign + - [x] implement TALER_exchange_offline_denom_validity_verify + - [x] 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 + - [ ] implement a robust and zero-cost marshalling abstraction + - [ ] factor out types and helper functions to own package codeblau.de/taler + - [ ] implement full functionality from origin */ package main @@ -355,6 +356,13 @@ func (es *EdDSASignature) MarshalJSON() (b []byte, e error) { return b, nil } +func (es *EdDSASignature) BinaryMarshal() []byte { + var buf = make([]byte, len(es.R)+len(es.S)) + copy(buf, es.R) + copy(buf[len(es.R):], es.S) + return buf +} + type RSAPublicKey rsa.PublicKey // following gnunet/src/json/json_helper.c and gnunet/src/util/crypto_rsa.c @@ -445,7 +453,71 @@ func (h *SHA512Hash) MarshalJSON() ([]byte, error) { return b, nil } -func auditorSignDenom(denom *DenomKey, ahash SHA512Hash, master *EdDSAPublicKey, pk *ed25519.PrivateKey) (SHA512Hash, EdDSASignature) { +func Verify(denom *DenomKey, master *EdDSAPublicKey, sig []byte) bool { + const TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY = 1025 + /* + data := struct { + size uint32 + purpose uint32 + master EdDSAPublicKey + start AbsoluteTime + expire_withdraw AbsoluteTime + expire_deposit AbsoluteTime + expire_legal AbsoluteTime + value Amount + fee_withdraw Amount + fee_deposit Amount + fee_refresh Amount + fee_refund Amount + denom_hash SHA512Hash + }{ + size: 4 + 4 + ed25519.PublicKeySize + 4*8 + 5*(8+4+len(denom.Value.Currency)) + sha512.Size, + purpose: TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY, + master: input.Arguments.MasterPublicKey, + } + */ + size := 4 + // size + 4 + // purpose + ed25519.PublicKeySize + // master + 4*8 + // start and expire* + 5*(8+4+len(denom.Value.Currency)) + // value and fee* + sha512.Size // denomHash + buf := make([]byte, size) + + n := 0 + be.PutUint32(buf[n:], uint32(size)) + n += 4 + be.PutUint32(buf[n:], TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY) + n += 4 + copy(buf[n:], *master) + n += len(*master) + for _, v := range []uint64{ + denom.StampStart.TMs, + denom.StampExpireWithdraw.TMs, + denom.StampExpireDeposit.TMs, + denom.StampExpireLegal.TMs, + } { + be.PutUint64(buf[n:], v*1000) // milli -> micro + n += 8 + } + for _, v := range [][]byte{ + denom.Value.Binary(), + denom.FeeWithdraw.Binary(), + denom.FeeDeposit.Binary(), + denom.FeeRefresh.Binary(), + denom.FeeRefund.Binary(), + } { + copy(buf[n:], v) + n += len(v) + } + bin := denom.DenomPub.Binary() + hash := sha512.Sum512(bin) + copy(buf[n:], hash[:]) + + return ed25519.Verify(ed25519.PublicKey(*master), buf, sig) +} + +func SignDenom(denom *DenomKey, ahash SHA512Hash, master *EdDSAPublicKey, pk *ed25519.PrivateKey) (SHA512Hash, EdDSASignature) { const TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS = 1064 @@ -516,18 +588,21 @@ func auditorSignDenom(denom *DenomKey, ahash SHA512Hash, master *EdDSAPublicKey, return hash, EdDSASignature{R: sig[:32], S: sig[32:]} } -func auditorSign(input *Input, url string, pk ed25519.PrivateKey) []SignOperation { +func Sign(input *Input, url string, pk ed25519.PrivateKey) ([]SignOperation, error) { output := make([]SignOperation, len(input.Arguments.Denoms)) for i, denom := range input.Arguments.Denoms { + if !Verify(&denom, &input.Arguments.MasterPublicKey, denom.MasterSig.BinaryMarshal()) { + return nil, fmt.Errorf("couldn verify denomination no. %d: %v", i+1, denom.DenomPub) + } output[i].Operation = "auditor-sign-denomination-0" - hash, sig := auditorSignDenom(&denom, sha512.Sum512(append([]byte(url), 0)), &input.Arguments.MasterPublicKey, &pk) + hash, sig := SignDenom(&denom, sha512.Sum512(append([]byte(url), 0)), &input.Arguments.MasterPublicKey, &pk) output[i].Arguments.HDenumPub = hash output[i].Arguments.AuditorSig = sig } - return output + return output, nil } var ( @@ -558,8 +633,10 @@ func main() { log.Fatal(e) } - // TODO: here needs to go the call to TALER_exchange_offline_denom_validity_verify - output := auditorSign(input, *url, pk) + output, err := Sign(input, *url, pk) + if err != nil { + log.Fatalf("error signing: %v", err) + } enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ")