cashless2ecash

cashless2ecash: pay with cards for digital cash (experimental)
Log | Files | Refs | README

encoding.go (2536B)


      1 package main
      2 
      3 import (
      4 	"errors"
      5 	"math"
      6 	"strings"
      7 )
      8 
      9 func talerBinaryEncode(byts []byte) string {
     10 
     11 	return encodeCrock(byts)
     12 	//return talerBase32Encoding().EncodeToString(byts)
     13 }
     14 
     15 func talerBinaryDecode(str string) ([]byte, error) {
     16 
     17 	return decodeCrock(str)
     18 }
     19 
     20 func ParseWopid(wopid string) ([]byte, error) {
     21 
     22 	wopidBytes, err := talerBinaryDecode(wopid)
     23 	if err != nil {
     24 		return nil, err
     25 	}
     26 
     27 	if len(wopidBytes) != 32 {
     28 		err = errors.New("invalid wopid")
     29 		return nil, err
     30 	}
     31 
     32 	return wopidBytes, nil
     33 }
     34 
     35 func FormatWopid(wopid []byte) string {
     36 
     37 	return talerBinaryEncode(wopid)
     38 }
     39 
     40 func ParseEddsaPubKey(key EddsaPublicKey) ([]byte, error) {
     41 
     42 	return talerBinaryDecode(string(key))
     43 }
     44 
     45 func FormatEddsaPubKey(key []byte) EddsaPublicKey {
     46 
     47 	return EddsaPublicKey(talerBinaryEncode(key))
     48 }
     49 
     50 func decodeCrock(e string) ([]byte, error) {
     51 	size := len(e)
     52 	bitpos := 0
     53 	bitbuf := 0
     54 	readPosition := 0
     55 	outLen := int(math.Floor((float64(size) * 5.0) / 8.0))
     56 	out := make([]byte, outLen)
     57 	outPos := 0
     58 
     59 	getValue := func(c byte) (int, error) {
     60 		alphabet := "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
     61 		switch c {
     62 		case 'o', 'O':
     63 			return 0, nil
     64 		case 'i', 'I', 'l', 'L':
     65 			return 1, nil
     66 		case 'u', 'U':
     67 			return 27, nil
     68 		}
     69 
     70 		i := strings.IndexRune(alphabet, rune(c))
     71 		if i > -1 && i < 32 {
     72 			return i, nil
     73 		}
     74 
     75 		return -1, errors.New("encoding error")
     76 	}
     77 
     78 	for readPosition < size || bitpos > 0 {
     79 		if readPosition < size {
     80 			v, err := getValue(e[readPosition])
     81 			if err != nil {
     82 				return nil, err
     83 			}
     84 			readPosition++
     85 			bitbuf = bitbuf<<5 | v
     86 			bitpos += 5
     87 		}
     88 		for bitpos >= 8 {
     89 			d := byte(bitbuf >> (bitpos - 8) & 0xff)
     90 			out[outPos] = d
     91 			outPos++
     92 			bitpos -= 8
     93 		}
     94 		if readPosition == size && bitpos > 0 {
     95 			bitbuf = bitbuf << (8 - bitpos) & 0xff
     96 			if bitbuf == 0 {
     97 				bitpos = 0
     98 			} else {
     99 				bitpos = 8
    100 			}
    101 		}
    102 	}
    103 	return out, nil
    104 }
    105 
    106 func encodeCrock(data []byte) string {
    107 	out := ""
    108 	bitbuf := 0
    109 	bitpos := 0
    110 
    111 	encodeValue := func(value int) byte {
    112 		alphabet := "ABCDEFGHJKMNPQRSTVWXYZ"
    113 		switch {
    114 		case value >= 0 && value <= 9:
    115 			return byte('0' + value)
    116 		case value >= 10 && value <= 31:
    117 			return alphabet[value-10]
    118 		default:
    119 			panic("Invalid value for encoding")
    120 		}
    121 	}
    122 
    123 	for _, b := range data {
    124 		bitbuf = bitbuf<<8 | int(b&0xff)
    125 		bitpos += 8
    126 		for bitpos >= 5 {
    127 			value := bitbuf >> (bitpos - 5) & 0x1f
    128 			out += string(encodeValue(value))
    129 			bitpos -= 5
    130 		}
    131 	}
    132 	if bitpos > 0 {
    133 		bitbuf = bitbuf << (5 - bitpos)
    134 		value := bitbuf & 0x1f
    135 		out += string(encodeValue(value))
    136 	}
    137 	return out
    138 }