diff options
| -rw-r--r-- | cmd/taler-auditor-offline-signing/main.go | 97 | 
1 files changed, 87 insertions, 10 deletions
| 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("", "  ") | 
