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 }