output encoding of keys with crockford (the Taler flavor) done

This commit is contained in:
Özgür Kesim 2021-10-19 10:56:33 +02:00
parent 03d90c406c
commit 63963e3fa5
Signed by: oec
GPG Key ID: 3D76A56D79EDD9D7

View File

@ -28,11 +28,9 @@ import (
"os" "os"
"regexp" "regexp"
"strconv" "strconv"
"github.com/davecgh/go-spew/spew"
) )
type Data struct { type Input struct {
Operation string `json:"operation"` Operation string `json:"operation"`
Arguments struct { Arguments struct {
Version string `json:"version"` Version string `json:"version"`
@ -90,6 +88,20 @@ func (ep *EdDSAPublicKey) UnmarshalJSON(in []byte) (e error) {
return nil return nil
} }
func (ep *EdDSAPublicKey) MarshalJSON() ([]byte, error) {
enc, e := crockfordEncode([]byte(*ep))
if e != nil {
return nil, e
}
buf := make([]byte, len(enc)+2)
buf[0] = '"'
buf[len(buf)-1] = '"'
copy(buf[1:], enc)
return buf, nil
}
const ( const (
CURRENCY_LEN = 12 CURRENCY_LEN = 12
CURRENCY_LEN_STR = "12" CURRENCY_LEN_STR = "12"
@ -246,10 +258,39 @@ func getValue(a byte) int {
return -1 return -1
} }
// Copy of GNUNET_STRINGS_data_to_string from gnunet/src/util/strings.c
func crockfordEncode(in []byte) ([]byte, error) {
const encTable = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
var (
out []byte
rpos, bits, vbit int
)
for rpos < len(in) || vbit > 0 {
if rpos < len(in) && vbit < 5 {
bits = (bits << 8) | int(in[rpos]) // eat 8 more bits
rpos++
vbit += 8
}
if vbit < 5 {
bits <<= (5 - vbit) // zero-padding
if vbit != (len(in)*8)%5 {
return nil, fmt.Errorf("vbit (%d) != (len(in)*8)%%5 (%d)", vbit, (len(in)*8)%5)
}
vbit = 5
}
vbit -= 5
out = append(out, encTable[(bits>>vbit)&31])
}
return out, nil
}
func (es *EdDSASignature) UnmarshalJSON(in []byte) (e error) { func (es *EdDSASignature) UnmarshalJSON(in []byte) (e error) {
var buf []byte var buf []byte
// 1. decode crockford.base32 // Decode crockford.base32, the Taler flavour
if buf, e = crockfordDecode(bytes.Trim(in, `"`)); e != nil { if buf, e = crockfordDecode(bytes.Trim(in, `"`)); e != nil {
return fmt.Errorf("couldn't decode EdDSASignature as crockford.base32: %v (%v)", e, string(in)) return fmt.Errorf("couldn't decode EdDSASignature as crockford.base32: %v (%v)", e, string(in))
} else if len(buf) != 64 { } else if len(buf) != 64 {
@ -262,13 +303,31 @@ func (es *EdDSASignature) UnmarshalJSON(in []byte) (e error) {
return nil return nil
} }
func (es *EdDSASignature) MarshalJSON() (b []byte, e error) {
var buf = make([]byte, len(es.R)+len(es.S))
copy(buf, es.R)
copy(buf[len(es.R):], es.S)
enc, err := crockfordEncode(buf)
if err != nil {
return nil, err
}
b = make([]byte, len(enc)+2)
b[0] = '"'
b[len(b)-1] = '"'
copy(b[1:], enc)
return b, nil
}
type RSAPublicKey rsa.PublicKey type RSAPublicKey rsa.PublicKey
// following gnunet/src/json/json_helper.c and gnunet/src/util/crypto_rsa.c // following gnunet/src/json/json_helper.c and gnunet/src/util/crypto_rsa.c
func (ep *RSAPublicKey) UnmarshalJSON(in []byte) (e error) { func (ep *RSAPublicKey) UnmarshalJSON(in []byte) (e error) {
var buf []byte var buf []byte
// 1. decode crockford.base32 // 1. decode crockford.base32, the Taler flavour
if buf, e = crockfordDecode(bytes.Trim(in, `"`)); e != nil { if buf, e = crockfordDecode(bytes.Trim(in, `"`)); e != nil {
return fmt.Errorf("couldn't decode EncodedRSAPublicKey as crockford.base32: %v (%v)", e, string(in)) return fmt.Errorf("couldn't decode EncodedRSAPublicKey as crockford.base32: %v (%v)", e, string(in))
} }
@ -296,16 +355,55 @@ func (ep *RSAPublicKey) UnmarshalJSON(in []byte) (e error) {
return nil return nil
} }
func (ep *RSAPublicKey) MarshalJSON() (b []byte, e error) {
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")
}
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)
enc, err := crockfordEncode(buf)
if err != nil {
return nil, err
}
b = make([]byte, len(enc)+2)
b[0] = '"'
b[len(b)-1] = '"'
copy(b[1:], enc)
return b, nil
}
type Output []SignOperation
type SignOperation struct {
Operation string `json:"operation"`
Arguments struct {
HDenumPub RSAPublicKey `json:"h_denum_pub"`
AuditorSig EdDSASignature `json:"auditor_sig"`
} `json:"arguments"`
}
func main() { func main() {
data := new(Data) input := new(Input)
dec := json.NewDecoder(os.Stdin) dec := json.NewDecoder(os.Stdin)
e := dec.Decode(data) e := dec.Decode(input)
if e != nil { if e != nil {
log.Fatal(e) log.Fatal(e)
} }
spew.Dump(data)
enc := json.NewEncoder(os.Stdout) enc := json.NewEncoder(os.Stdout)
enc.SetIndent("Data:", " ") enc.SetIndent("Input:", " ")
enc.Encode(data) e = enc.Encode(input)
if e != nil {
log.Fatal(e)
}
} }