diff --git a/cmd/taler-auditor-offline-signing/main.go b/cmd/taler-auditor-offline-signing/main.go index 330934e..c997165 100644 --- a/cmd/taler-auditor-offline-signing/main.go +++ b/cmd/taler-auditor-offline-signing/main.go @@ -1,5 +1,82 @@ package main +import ( + "crypto/rsa" + "encoding/binary" + "fmt" + "math/big" +) + +type Keys struct { + Denoms []DenomKey `json:"denoms"` + MasterPublicKey MasterPublicKey `json:"master_public_key"` +} + +type MasterPublicKey [256 / 8]byte + +type DenomKey struct { + DenomPub EncodedRSAPublicKey `json:"denom_pub"` + Value Amount `json:"value"` + FeeWithdraw Amount `json:"fee_withdraw"` + FeeDeposit Amount `json:"fee_deposit"` + FeeRefresh Amount `json:"fee_refresh"` + FeeRefund Amount `json:"fee_refund"` + StampStart AbsoluteTime `json:"stamp_start"` + StampExpireWithdraw AbsoluteTime `json:"stamp_expire_withdraw"` + StampExpireDeposit AbsoluteTime `json:"stamp_expire_deposit"` + StampExpireLegal AbsoluteTime `json:"stamp_expire_legal"` + MasterSig EdDSASignature `json:"master_sig"` +} + +type EncodedRSAPublicKey []byte + +const ( + CURRENCY_LEN = 12 + CURRENCY_LEN_STR = "12" +) + +type Amount struct { + Value uint64 `json:"value"` + Fraction uint32 `json:"fraction"` + Currency [CURRENCY_LEN]byte `json:"currency"` +} + +type AbsoluteTime uint64 + +type EdDSASignature struct { + R [256 / 8]byte `json:"r"` + S [256 / 8]byte `json:"s"` +} + +// following gnunet/src/util/crypto_rsa.c +func (ep *EncodedRSAPublicKey) Decode() (p rsa.PublicKey, e error) { + buf := []byte(*ep) + if len(buf) < 4 { + e = fmt.Errorf("byte array too small for RSA public key header") + return + } + + modulus_length, public_exponent_length := binary.BigEndian.Uint16(buf[0:]), binary.BigEndian.Uint16(buf[2:]) + if len(buf[4:]) != int(modulus_length)+int(public_exponent_length) { + e = fmt.Errorf("byte array has wrong size according to encoded length's for modulus and public exponent") + return + } + + // BUG! This is most likely wrong. + // Consult _gcry_mpi_set_buffer from libgcrypt-1.9.4/mpi/mpicoder.c + buf = buf[4:] + p.N = big.NewInt(0).SetBytes(buf[:modulus_length]) + buf = buf[modulus_length:] + ex := big.NewInt(0).SetBytes(buf[:public_exponent_length]) // binary.BigEndian.Uint64 instead? + if !ex.IsInt64() { + e = fmt.Errorf("public exponent is not int64") + return + } + p.E = int(ex.Int64()) + + return p, e +} + func main() { panic("nothing implemented yet.") }