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  }