github.com/danil/iso8583@v0.21.0/codec8583/codec8583.go (about) 1 package codec8583 2 3 import ( 4 "crypto/sha256" 5 "encoding/base64" 6 "encoding/hex" 7 "fmt" 8 "hash" 9 "io" 10 "regexp" 11 "strconv" 12 "sync" 13 ) 14 15 const Tag8583 = "iso8583" 16 17 // Format maps a codes to a MIT/bitmaps/each individual field of the ISO 8583 message. 18 type Format map[int]Codec 19 20 var ( 21 // MTIAsciiCodec encodes/decodes ISO 8583 MTI (Message Type Indicator) 22 // the size of which is 4 bytes in ASCII character encoding. 23 MTIAsciiCodec = FIX{4, ASCII, EncodeMTI, DecodeMTI} 24 // MTIEbcdicCodec encodes/decodes ISO 8583 MTI (Message Type Indicator) 25 // the size of which is 4 bytes in EBCDIC character encoding. 26 MTIEbcdicCodec = FIX{4, EBCDIC, EncodeMTI, DecodeMTI} 27 // BitmapCodec encodes/decodes ISO 8583 bitmap the size of which is 8 bytes (64 bit). 28 BitmapCodec = FIX{8, NOPCharset, EncBitmap, DecBitmap} 29 ) 30 31 type ( 32 // EncodeFunc encodes ISO 8583 MTI/bitmaps/fields. 33 EncodeFunc func(Hasher, Codec, []byte) ([]byte, error) 34 // DecodeFunc decodes ISO 8583 MTI/bitmaps/fields. 35 DecodeFunc func(Hasher, Codec, []byte) ([]byte, error) 36 ) 37 38 // EncodeMTI intends to encode the ISO 8583 MTI (Message Type Indicator). 39 func EncodeMTI(_ Hasher, codec Codec, dec []byte) ([]byte, error) { return codec.Charset().Encode(dec) } 40 41 // EncBitmap intends to encode the ISO 8583 bitmap. 42 func EncBitmap(_ Hasher, _ Codec, dec []byte) ([]byte, error) { return dec, nil } 43 44 // EncA intends to encode Alpha, including blanks <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 45 func EncA(_ Hasher, codec Codec, dec []byte) ([]byte, error) { return codec.Charset().Encode(dec) } 46 47 // EncN intends to encode numeric values only <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 48 func EncN(_ Hasher, codec Codec, dec []byte) ([]byte, error) { return codec.Charset().Encode(dec) } 49 50 // EncXN intends to encode numeric (amount) values, 51 // where the first byte is either 'C' to indicate a positive or Credit value, 52 // or 'D' to indicate a negative or Debit value, 53 // followed by the numeric value (using n digits) 54 // <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 55 func EncXN(_ Hasher, codec Codec, dec []byte) ([]byte, error) { return codec.Charset().Encode(dec) } 56 57 // EncNS intends to encode numeric and special characters only <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 58 func EncNS(_ Hasher, codec Codec, dec []byte) ([]byte, error) { return codec.Charset().Encode(dec) } 59 60 // EncAN intends to encode alphanumeric <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 61 func EncAN(_ Hasher, codec Codec, dec []byte) ([]byte, error) { return codec.Charset().Encode(dec) } 62 63 // EncANS intends to encode alphabetic, numeric and special characters <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 64 func EncANS(_ Hasher, codec Codec, dec []byte) ([]byte, error) { return codec.Charset().Encode(dec) } 65 66 // EncZ intends to encode tracks 2 and 3 code set as defined in ISO/IEC 7813 and ISO/IEC 4909 respectively 67 // <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>, 68 // <https://en.wikipedia.org/wiki/ISO/IEC_7813>. 69 func EncZ(_ Hasher, codec Codec, dec []byte) ([]byte, error) { return codec.Charset().Encode(dec) } 70 71 // EncB intends to encode binary data <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 72 func EncB(_ Hasher, _ Codec, dec []byte) ([]byte, error) { 73 enc := make([]byte, base64.StdEncoding.DecodedLen(len(dec))) 74 n, err := base64.StdEncoding.Decode(enc, dec) 75 return enc[:n], err 76 } 77 78 // DecodeMTI intends to decode the ISO 8583 MTI (Message Type Indicator). 79 func DecodeMTI(_ Hasher, codec Codec, enc []byte) ([]byte, error) { return codec.Charset().Decode(enc) } 80 81 // DecBitmap intends to decode the ISO 8583 bitmap. 82 func DecBitmap(_ Hasher, _ Codec, enc []byte) ([]byte, error) { return enc, nil } 83 84 // DecA intends to decode Alpha, including blanks <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 85 func DecA(_ Hasher, codec Codec, enc []byte) ([]byte, error) { return codec.Charset().Decode(enc) } 86 87 // DecN intends to decode numeric values only <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 88 func DecN(_ Hasher, codec Codec, enc []byte) ([]byte, error) { return codec.Charset().Decode(enc) } 89 90 // DecXN intends to decode numeric (amount) values, 91 // where the first byte is either 'C' to indicate a positive or Credit value, 92 // or 'D' to indicate a negative or Debit value, 93 // followed by the numeric value (using n digits) 94 // <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 95 func DecXN(_ Hasher, codec Codec, enc []byte) ([]byte, error) { return codec.Charset().Decode(enc) } 96 97 // DecAN intends to decode alphanumeric <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 98 func DecAN(_ Hasher, codec Codec, enc []byte) ([]byte, error) { return codec.Charset().Decode(enc) } 99 100 // DecNS intends to decode numeric and special characters only <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 101 func DecNS(_ Hasher, codec Codec, enc []byte) ([]byte, error) { return codec.Charset().Decode(enc) } 102 103 // DecANS intends to decode alphabetic, numeric and special characters <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 104 func DecANS(_ Hasher, codec Codec, enc []byte) ([]byte, error) { return codec.Charset().Decode(enc) } 105 106 // DecZ intends to decode tracks 2 and 3 code set as defined in ISO/IEC 7813 and ISO/IEC 4909 respectively 107 // <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>, 108 // <https://en.wikipedia.org/wiki/ISO/IEC_7813>. 109 func DecZ(_ Hasher, codec Codec, enc []byte) ([]byte, error) { return codec.Charset().Decode(enc) } 110 111 // DecB intends to decode binary data <https://en.wikipedia.org/wiki/ISO_8583#Data_elements>. 112 func DecB(_ Hasher, _ Codec, enc []byte) ([]byte, error) { 113 dec := make([]byte, base64.StdEncoding.EncodedLen(len(enc))) 114 base64.StdEncoding.Encode(dec, enc) 115 return dec, nil 116 } 117 118 // DecNullify just skips the field. 119 func DecNullify(_ Hasher, _ Codec, _ []byte) ([]byte, error) { return []byte{}, nil } 120 121 // DecPANTruncate intends to decode and truncate (mask) PAN, 122 // 1234567890123456 -> 1234XXXXXXXX3456. 123 func DecPANTruncate(_ Hasher, codec Codec, enc []byte) ([]byte, error) { 124 dec, err := codec.Charset().Decode(enc) 125 if err != nil { 126 return nil, err 127 } 128 for i := 4; i < len(dec)-4; i++ { 129 dec[i] = 'X' 130 } 131 return dec, nil 132 } 133 134 // DecFirstPANTruncate intends to decode and truncate (mask) PAN located at the beginning of the byte slice, 135 // 1234567890123456D99122011969100000377 -> 1234XXXXXXXX3456D99122011969100000377 136 func DecFirstPANTruncate(_ Hasher, codec Codec, enc []byte) ([]byte, error) { 137 dec, err := codec.Charset().Decode(enc) 138 if err != nil { 139 return nil, err 140 } 141 re, err := regexp.Compile("[^0-9]") 142 if err != nil { 143 return nil, err 144 } 145 loc := re.FindIndex(dec) 146 l := len(dec) 147 if loc != nil { 148 l = loc[0] 149 } 150 for i := 4; i < l-4; i++ { 151 dec[i] = 'X' 152 } 153 return dec, nil 154 } 155 156 // DecHash256 intends to decode and hash (obfuscate) 157 // like Central Bank of the Russian Federation obfuscates PAN, 158 // using the SHA 256 sum function. 159 func DecHash256(h Hasher, codec Codec, enc []byte) ([]byte, error) { 160 dec, err := codec.Charset().Decode(enc) 161 if err != nil { 162 return nil, err 163 } 164 s256, err := h.Sum256(dec) 165 if err != nil { 166 return nil, err 167 } 168 return []byte(hex.EncodeToString(s256)), nil 169 } 170 171 // Codec encodes/decodes a MTI/bitmaps/fields of the ISO 8583 message. 172 type Codec interface { 173 Encode(Hasher, []byte) ([]byte, error) 174 Decode(Hasher, []byte) ([]byte, error) 175 Read(io.Reader) ([]byte, error) 176 Write(io.Writer, []byte) error 177 Len() int 178 Charset() Charset 179 } 180 181 // FIX is an codec for a fixed length fields/MTI/bitmaps of the ISO 8583. 182 type FIX struct { 183 Length int 184 ChrSet Charset 185 Enc EncodeFunc 186 Dec DecodeFunc 187 } 188 189 func (c FIX) Len() int { return c.Length } 190 func (c FIX) Charset() Charset { return c.ChrSet } 191 func (c FIX) Encode(h Hasher, dec []byte) ([]byte, error) { return c.Enc(h, c, dec) } 192 func (c FIX) Decode(h Hasher, enc []byte) ([]byte, error) { return c.Dec(h, c, enc) } 193 194 const ( 195 fldMinLen = 1 196 fldMaxLen = 999 197 ) 198 199 // Read reads a field with fixed length. 200 func (c FIX) Read(r io.Reader) ([]byte, error) { 201 if c.Length < fldMinLen { 202 return nil, fmt.Errorf("fixed field length too small to read: %d < %d", c.Length, fldMinLen) 203 } 204 if c.Length > fldMaxLen { 205 return nil, fmt.Errorf("fixed field length too big to read: %d > %d", c.Length, fldMaxLen) 206 } 207 data := make([]byte, c.Length) 208 _, err := r.Read(data) 209 return data, err 210 } 211 212 // Write writes a field with fixed length. 213 func (c FIX) Write(w io.Writer, data []byte) error { 214 if c.Length < fldMinLen { 215 return fmt.Errorf("fixed field length too small to write: %d < %d", c.Length, fldMinLen) 216 } 217 if c.Length > fldMaxLen { 218 return fmt.Errorf("fixed field length too big to write: %d > %d", c.Length, fldMaxLen) 219 } 220 _, err := w.Write(data) 221 return err 222 } 223 224 // LVAR is an codec for the variable length fields of the ISO 8583, 225 // the length coded in 1 byte. 226 type LVAR struct { 227 MaxLen int 228 ChrSet Charset 229 Enc EncodeFunc 230 Dec DecodeFunc 231 } 232 233 func (c LVAR) Len() int { return c.MaxLen } 234 func (c LVAR) Charset() Charset { return c.ChrSet } 235 func (c LVAR) Encode(h Hasher, dec []byte) ([]byte, error) { return c.Enc(h, c, dec) } 236 func (c LVAR) Decode(h Hasher, enc []byte) ([]byte, error) { return c.Dec(h, c, enc) } 237 238 // Read reads a field with variable length (VAR). 239 func (c LVAR) Read(r io.Reader) ([]byte, error) { 240 return varRead(r, 1, c.MaxLen, c.ChrSet.Dec) 241 } 242 243 // Write writes a field with variable length (VAR). 244 func (c LVAR) Write(w io.Writer, data []byte) error { 245 return varWrite(w, data, 1, c.MaxLen, c.ChrSet.Enc) 246 } 247 248 // LLVAR is an codec for the variable length fields of the ISO 8583, 249 // the length coded in 2 bytes. 250 type LLVAR struct { 251 MaxLen int 252 ChrSet Charset 253 Enc EncodeFunc 254 Dec DecodeFunc 255 } 256 257 func (c LLVAR) Len() int { return c.MaxLen } 258 func (c LLVAR) Charset() Charset { return c.ChrSet } 259 func (c LLVAR) Encode(h Hasher, dec []byte) ([]byte, error) { return c.Enc(h, c, dec) } 260 func (c LLVAR) Decode(h Hasher, enc []byte) ([]byte, error) { return c.Dec(h, c, enc) } 261 262 // Read reads a field with variable length (VAR). 263 func (c LLVAR) Read(r io.Reader) ([]byte, error) { 264 return varRead(r, 2, c.MaxLen, c.ChrSet.Dec) 265 } 266 267 // Write writes a field with variable length (VAR). 268 func (c LLVAR) Write(w io.Writer, data []byte) error { 269 return varWrite(w, data, 2, c.MaxLen, c.ChrSet.Enc) 270 } 271 272 // LLLVAR is an codec for the variable length fields of the ISO 8583, 273 // the length coded in 3 bytes. 274 type LLLVAR struct { 275 MaxLen int 276 ChrSet Charset 277 Enc EncodeFunc 278 Dec DecodeFunc 279 } 280 281 func (c LLLVAR) Len() int { return c.MaxLen } 282 func (c LLLVAR) Charset() Charset { return c.ChrSet } 283 func (c LLLVAR) Encode(h Hasher, dec []byte) ([]byte, error) { return c.Enc(h, c, dec) } 284 func (c LLLVAR) Decode(h Hasher, enc []byte) ([]byte, error) { return c.Dec(h, c, enc) } 285 286 // Read reads a field with variable length (VAR). 287 func (c LLLVAR) Read(r io.Reader) ([]byte, error) { 288 return varRead(r, 3, c.MaxLen, c.ChrSet.Dec) 289 } 290 291 // Write writes a field with variable length (VAR). 292 func (c LLLVAR) Write(w io.Writer, data []byte) error { 293 return varWrite(w, data, 3, c.MaxLen, c.ChrSet.Enc) 294 } 295 296 // varRead reads a field with variable length (VAR). 297 func varRead(r io.Reader, lenOfLen, maxLen int, dec DecodeCharsetFunc) ([]byte, error) { 298 raw := make([]byte, lenOfLen) 299 _, err := r.Read(raw) 300 if err != nil { 301 return nil, err 302 } 303 if dec != nil { 304 raw, err = dec(raw) 305 if err != nil { 306 return nil, err 307 } 308 } 309 var length int 310 length, err = strconv.Atoi(string(raw)) 311 if err != nil { 312 return nil, err 313 } 314 if length < fldMinLen { 315 return nil, fmt.Errorf("VAR field length too small to read: %d < %d", length, fldMinLen) 316 } 317 if length > maxLen { 318 return nil, fmt.Errorf("VAR field length too big to read: %d > %d", length, maxLen) 319 } 320 data := make([]byte, length) 321 _, err = r.Read(data) 322 return data, err 323 } 324 325 // varWrite writes a field with variable length (VAR). 326 func varWrite(w io.Writer, data []byte, lenOfLen, maxLen int, enc EncodeCharsetFunc) error { 327 if len(data) < fldMinLen { 328 return fmt.Errorf("field value length is too small to write: %d < %d", len(data), fldMinLen) 329 } 330 if len(data) > maxLen || maxLen > fldMaxLen { 331 return fmt.Errorf("field value length is too big to write: %d > %d", len(data), maxLen) 332 } 333 rawLengthOfLength := []byte(fmt.Sprintf("%0"+strconv.Itoa(lenOfLen)+"d", len(data))) 334 var err error 335 if enc != nil { 336 rawLengthOfLength, err = enc(rawLengthOfLength) 337 if err != nil { 338 return err 339 } 340 } 341 _, err = w.Write(rawLengthOfLength) 342 if err != nil { 343 return err 344 } 345 _, err = w.Write([]byte(data)) 346 return err 347 } 348 349 type Hasher interface { 350 Sum256(data []byte) ([]byte, error) 351 } 352 353 func NewHashify() hashify { return hashify{} } 354 355 type hashify struct{} 356 357 var pool = sync.Pool{New: func() interface{} { return sha256.New() }} 358 359 func (h hashify) Sum256(data []byte) ([]byte, error) { 360 h256 := pool.Get().(hash.Hash) 361 h256.Reset() 362 defer pool.Put(h256) 363 364 _, err := h256.Write(data) 365 if err != nil { 366 return nil, err 367 } 368 return h256.Sum(nil), nil 369 }