aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÖzgür Kesim <oec-taler@kesim.org>2021-10-23 16:47:48 +0200
committerÖzgür Kesim <oec-taler@kesim.org>2021-10-23 16:47:48 +0200
commit98f1e7ef3dbecbe6cfdfdc74a551e988c8a0cfde (patch)
tree09897596dd9ba0971a5fca4db4a75e2605a4a248
parent27d2fbe8043fedbe6d73fa86649acc3d087ed67b (diff)
signing operation works. PoC quality
-rw-r--r--cmd/taler-auditor-offline-signing/main.go159
1 files changed, 133 insertions, 26 deletions
diff --git a/cmd/taler-auditor-offline-signing/main.go b/cmd/taler-auditor-offline-signing/main.go
index 92db7b2..dfbfd0c 100644
--- a/cmd/taler-auditor-offline-signing/main.go
+++ b/cmd/taler-auditor-offline-signing/main.go
@@ -34,6 +34,8 @@ import (
"strconv"
)
+var be = binary.BigEndian
+
type Input struct {
Operation string `json:"operation"`
Arguments struct {
@@ -106,15 +108,12 @@ func (ep *EdDSAPublicKey) MarshalJSON() ([]byte, error) {
return buf, nil
}
-const (
- CURRENCY_LEN = 12
- CURRENCY_LEN_STR = "12"
-)
+const CURRENCY_LEN = 12
type Amount struct {
- Value uint64 `json:"value"`
- Fraction uint32 `json:"fraction"`
- Currency string `json:"currency"`
+ Value uint64 `json:"value"`
+ Fraction uint32 `json:"fraction"`
+ Currency [CURRENCY_LEN]byte `json:"currency"`
}
// Amount comes in as something like "CHF:0.32"
@@ -129,7 +128,7 @@ func (a *Amount) UnmarshalJSON(in []byte) (e error) {
} else if len(parts[0]) >= CURRENCY_LEN || nonAllowedCharsRX.Match(parts[0]) {
return fmt.Errorf("invalid currency")
}
- a.Currency = string(parts[0])
+ copy(a.Currency[:], parts[0][:])
// split and parse Value
parts = bytes.Split(parts[1], []byte("."))
@@ -145,16 +144,47 @@ func (a *Amount) UnmarshalJSON(in []byte) (e error) {
if len(parts) == 2 {
if len(parts[1]) == 0 || len(parts[1]) > 8 {
return fmt.Errorf("invalid fraction")
- } else if v, e := strconv.ParseUint(string(parts[1]), 10, 32); e != nil {
+ } else if a.Fraction, e = parseFraction(parts[1]); e != nil {
return e
- } else {
- a.Fraction = uint32(v)
}
}
return nil
}
+// following exchange/src/util/amount.c TALER_string_to_amount()
+func parseFraction(input []byte) (uint32, error) {
+ const TALER_AMOUNT_FRAC_BASE = 100_000_000
+
+ b := uint32(TALER_AMOUNT_FRAC_BASE / 10)
+
+ var f uint32
+
+ for _, c := range input {
+ if b == 0 {
+ return 0, fmt.Errorf("fractional value too small")
+ }
+
+ if c < '0' || c > '9' {
+ return 0, fmt.Errorf("invalid fractional value")
+ }
+
+ f += uint32(c-'0') * b
+ b /= 10
+ }
+
+ return f, nil
+
+}
+
+func (a *Amount) Binary() []byte {
+ buf := make([]byte, 8+4+CURRENCY_LEN)
+ be.PutUint64(buf, a.Value)
+ be.PutUint32(buf[8:], a.Fraction)
+ copy(buf[8+4:], a.Currency[:CURRENCY_LEN])
+ return buf
+}
+
type EdDSASignature struct {
R []byte `json:"r"`
S []byte `json:"s"`
@@ -399,10 +429,10 @@ type SignOperation struct {
} `json:"arguments"`
}
-type SHA512Hash []byte
+type SHA512Hash [sha512.Size]byte
func (h *SHA512Hash) MarshalJSON() ([]byte, error) {
- enc, err := crockfordEncode(*h)
+ enc, err := crockfordEncode((*h)[:])
if err != nil {
return nil, fmt.Errorf("error encoding %v: %e\n", h, err)
}
@@ -415,7 +445,95 @@ func (h *SHA512Hash) MarshalJSON() ([]byte, error) {
return b, nil
}
-var keyfile = flag.String("key", "", "filename of EC25519 private key")
+func auditorSignDenom(denom *DenomKey, ahash SHA512Hash, master *EdDSAPublicKey, pk *ed25519.PrivateKey) (SHA512Hash, EdDSASignature) {
+
+ const TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS = 1064
+
+ /*
+ We write a bigendian encoded version of ExchangeKeyValidityPS.
+
+ type Purpose uint32
+ type ExchangeKeyValidityPS struct {
+ size uint32
+ purpose Purpose
+ auditor_url_hash SHA512Hash
+ master EdDSAPublicKey
+ start AbsoluteTime
+ expireWithdraw AbsoluteTime
+ expireDeposit AbsoluteTime
+ expireLegal AbsoluteTime
+ value Amount
+ feeWithdraw Amount
+ feeDeposit Amount
+ feeRefresh Amount
+ feeRefund Amount
+ denomHash SHA512Hash
+ }
+ */
+
+ size := 4 + // size
+ 4 + // purpose
+ sha512.Size + // auditor_url_hash
+ 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_AUDITOR_EXCHANGE_KEYS)
+ n += 4
+ copy(buf[n:], ahash[:])
+ n += len(ahash)
+ 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[:])
+
+ sig := ed25519.Sign(*pk, buf)
+ return hash, EdDSASignature{R: sig[:32], S: sig[32:]}
+}
+
+func auditorSign(input *Input, url string, pk ed25519.PrivateKey) []SignOperation {
+
+ output := make([]SignOperation, len(input.Arguments.Denoms))
+ for i, denom := range input.Arguments.Denoms {
+ output[i].Operation = "auditor-sign-denomination-0"
+
+ hash, sig := auditorSignDenom(&denom, sha512.Sum512(append([]byte(url), 0)), &input.Arguments.MasterPublicKey, &pk)
+ output[i].Arguments.HDenumPub = hash
+ output[i].Arguments.AuditorSig = sig
+ }
+
+ return output
+}
+
+var (
+ keyfile = flag.String("key", "auditor.key", "filename of EC25519 private key")
+ url = flag.String("url", "https://auditor.codeblau.de/", "auditor url")
+)
func main() {
@@ -441,18 +559,7 @@ func main() {
}
// 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:]}
- }
+ output := auditorSign(input, *url, pk)
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")