func getDataInput(dataInput string, counter, question, password, session, timeStamp string) ([]byte, error) {
	ret := []byte{}
	val := []string{counter, question, password, session, timeStamp}
	for i, c := range ocraSuiteDataInputParseStruct {
		data, err := c.hFunc(dataInput, val[i], c)
		if err != nil {
			return nil, err
		}
		ret = append(ret, data...)
	}
	return ret, nil
}
Generate the data input to be used by the OCRA hash function.
This function uses the OCRA Suite as guidence for the relevant part of the OCRA Suite input strings
package ocra
import (
	"crypto/rand"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"math/big"
	"os"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	defs "github.com/ibm-security-innovation/libsecurity-go/defs"
	logger "github.com/ibm-security-innovation/libsecurity-go/logger"
	"github.com/ibm-security-innovation/libsecurity-go/otp"
	ss "github.com/ibm-security-innovation/libsecurity-go/storage"
)
type appendSide int
const (
	ocraSuiteOcraProtocolIdx = 0
	ocraSuiteCryptoIdx       = 1
	ocraSuiteDataInputIdx    = 2
	ocraSuiteNumOfFields     = 3
	ocraSuiteProtocolIdx     = 0
	ocraSuiteHashLengthIdx   = 2
	ocraSuiteSplitToken                    = ":"
	ocraSuiteDigitSplitToken               = "-"
	ocraSuiteDataInputSplitToken           = "-"
	ocraSuiteDataInputCounterToken         = "c"
	ocraSuiteDataInputQuestionToken        = "q"
	ocraSuiteDataInputQuestionNumericToken = "n"
	ocraSuiteDataInputQuestionAlfabetToken = "a"
	ocraSuiteDataInputPasswordToken        = "p"
	ocraSuiteDataInputSessionToken         = "s"
	ocraSuiteDataInputTimeStampToken       = "t"
	dataInputAppendToken                   = 0
	ocraSuiteOcraProtocol                  = "ocra-1"
	ocraSuiteProtocolToken                 = "hotp"
	ocraSuiteDataInputQuestionTypeOptions = "nah"
	minOcraSuiteDataInputQuestionLength   = 4
	maxOcraSuiteDataInputQuestionLength   = 64
	ocraSuiteCounterLengthB   = 8
	ocraSuiteQuestionLengthB  = 128
	ocraSuiteTimeStampLengthB = 8
	minKeyLength = 6
	maxKeyLength = 512
	appendToLeft  appendSide = 0
	appendToRight appendSide = 1
)
var (
	ocraSuiteDataInputParseStruct    []parseData
	ocraSuiteDataInputValidTokensMap = make(map[byte]parseData)
	ocraValidOutputLength            = []int{0, 4, 5, 6, 7, 8, 9, 10}
	ocraValidOutputLengthMap         = make(map[int]int)
	dataInputCounterRegExp           = regexp.MustCompile("^c([a-zA-Z0-9]*-)")
	dataInputQuestionRegExp          = regexp.MustCompile(fmt.Sprintf("%s([%s])([0-9]*)", ocraSuiteDataInputQuestionToken, ocraSuiteDataInputQuestionTypeOptions))
	timeStampRegExp                  = regexp.MustCompile("(t[1-9][sm]|t[1-5][0-9][sm]|t[0-9]h|t[1-3][0-9]h|t4[0-8]h)")
	dataInputTokenFmt                = "%s(%s[a-zA-Z0-9]*)"
	dataInputPasswordTokenRegExp     = regexp.MustCompile(fmt.Sprintf(dataInputTokenFmt, ocraSuiteDataInputSplitToken, ocraSuiteDataInputPasswordToken))
	dataInputSessionTokenRegExp      = regexp.MustCompile(fmt.Sprintf(dataInputTokenFmt, ocraSuiteDataInputSplitToken, ocraSuiteDataInputSessionToken))
	dataInputTimeStampTokenRegExp    = regexp.MustCompile(fmt.Sprintf(dataInputTokenFmt, ocraSuiteDataInputSplitToken, ocraSuiteDataInputTimeStampToken))
)
type UserOcra struct {
	OcraSuite string
	Key       []byte
}
func (u UserOcra) String() string {
	return fmt.Sprintf("Key: %v, OCRA Suite %v", u.Key, u.OcraSuite)
}
type parseData struct {
	token string
	cFunc func(string, string, parseData) (int, error)
	hFunc func(string, string, parseData) ([]byte, error)
	parse *regexp.Regexp
}
type inputData struct {
	name   string
	length int
}
func (d inputData) String() string {
	return fmt.Sprintf("Input data: name - '%v', length - %v", d.name, d.length)
}
type hashesData struct {
	name   string
	digest func() hash.Hash
	length int
}
var hashes = []hashesData{{"sha1", sha1.New, 0}, {"sha256", sha256.New, 0}, {"sha512", sha512.New, 0}}
var passwords = []inputData{{"psha1", 20}, {"psha256", 32}, {"psha512", 64}}
type Serializer struct{}
func init() {
	logger.Init(ioutil.Discard, ioutil.Discard, os.Stdout, os.Stderr)
	defs.Serializers[defs.OcraPropertyName] = &Serializer{}
	for _, val := range ocraValidOutputLength {
		ocraValidOutputLengthMap[val] = val
	}
	ocraSuiteDataInputParseStruct = []parseData{{ocraSuiteDataInputCounterToken, checkOcraDataInputCounterValidity, handleCounter, dataInputCounterRegExp},
		{ocraSuiteDataInputQuestionToken, checkOcraDataInputQuestionValidity, handleQuestion, dataInputQuestionRegExp},
		{ocraSuiteDataInputPasswordToken, checkOcraDataInputPasswordValidity, handlePassword, dataInputPasswordTokenRegExp},
		{ocraSuiteDataInputSessionToken, checkOcraDataInputSessionValidity, handleSession, dataInputSessionTokenRegExp},
		{ocraSuiteDataInputTimeStampToken, checkOcraDataInputTimeStampValidity, handleTimeStamp, dataInputTimeStampTokenRegExp}}
	for _, c := range ocraSuiteDataInputParseStruct {
		ocraSuiteDataInputValidTokensMap[c.token[0]] = c
	}
}
func appendStringToGivenLen(data []byte, l int, appendB byte, side appendSide) []byte {
	filler := []byte{}
	for i := len(data); i < l; i++ {
		filler = append(filler, appendB)
	}
	if side == appendToRight {
		return append(data, filler...)
	}
	return append(filler, data...)
}
func hexStrToHexByte(str string) ([]byte, error) {
	if len(str)%2 == 1 {
		str = "0" + str
	}
	return hex.DecodeString(str)
}
func numericStrToByte(str string) ([]byte, error) {
	n := &big.Int{}
	_, ok := n.SetString(str, 10)
	if ok == false {
		return nil, fmt.Errorf("The string '%v' is not a decimal string", str)
	}
	ret := fmt.Sprintf("%X", n)
	if len(ret)%2 == 1 {
		ret = ret + "0"
	}
	return hex.DecodeString(ret)
}
func handleCounter(dataInput string, counter string, p parseData) ([]byte, error) {
	length, err := p.cFunc(dataInput, "", p)
	if err != nil {
		return nil, err
	} else if length == 0 {
		return nil, nil
	}
	c1, err := hexStrToHexByte(counter)
	if err != nil {
		return nil, err
	}
	c2 := appendStringToGivenLen(c1, ocraSuiteCounterLengthB, dataInputAppendToken, appendToLeft)
	logger.Info.Println("Counter calculations: in command:", dataInput, ", Original counter:", counter, ", convert to:", c1, "The new counter is:", c2, ", len:", len(c2))
	return c2, nil
}
func handleQuestion(dataInput string, question string, p parseData) ([]byte, error) {
	var q1, q2 []byte
	var err error
	format, _, err := parseQuestion(dataInput, p)
	if err != nil {
		return nil, err
	}
	if format == ocraSuiteDataInputQuestionNumericToken {
		q1, err = numericStrToByte(question)
		if err != nil {
			return nil, err
		}
	} else {
		q1 = []byte(question)
	}
	q2 = appendStringToGivenLen(q1, ocraSuiteQuestionLengthB, dataInputAppendToken, appendToRight)
	logger.Info.Println("Question calculations: in command:", dataInput, ", Original question:", question, "converted to:", []byte(q1), "The new question is:", q2, ", len:", len(q2))
	return q2, nil
}
func handlePassword(dataInput string, password string, p parseData) ([]byte, error) {
	var p2 []byte
	pass, _, err := extractDataInputToken(dataInput, p)
	if err != nil {
		return nil, fmt.Errorf("OCRA Suite %v: Password error: %v", dataInput, err)
	}
	if len(pass) == 0 {
		return p2, nil
	}
	for _, p := range passwords {
		if pass == p.name {
			p1, err := hexStrToHexByte(password)
			if err != nil {
				return nil, err
			}
			p2 = appendStringToGivenLen(p1, p.length, dataInputAppendToken, appendToLeft)[0:p.length]
			logger.Info.Println("Password calculations: in command:", dataInput, ", match:", p.name, ", original password:", password, len(password), ", The new password is:", []byte(p2), ", len:", len(p2))
		}
	}
	return p2, nil
}
func handleSession(dataInput string, session string, p parseData) ([]byte, error) {
	var s2 []byte
	ses, _, err := extractDataInputToken(dataInput, p)
	if err != nil {
		return nil, fmt.Errorf("OCRA Suite %v: Session error: %v", dataInput, err)
	}
	if len(ses) == 0 {
		return nil, nil
	}
	length, err := p.cFunc(dataInput, session, p)
	if err != nil || length <= 0 {
		return nil, err
	}
	s1, err := hexStrToHexByte(session)
	if err != nil {
		return nil, err
	}
	s2 = appendStringToGivenLen(s1, length, dataInputAppendToken, appendToLeft)[0:length]
	logger.Info.Println("Session calculations: in command:", dataInput, ", session length:", length, ", The original session:", session, "Convert to:", s1, ", The new session is:", s2, ", len:", len(s2))
	return s2, nil
}
func handleTimeStamp(dataInput string, timeStamp string, p parseData) ([]byte, error) {
	var t2 []byte
	t, _, err := extractDataInputToken(dataInput, p)
	if err != nil {
		return nil, fmt.Errorf("OCRA Suite %v: Time stamp error: %v", dataInput, err)
	}
	if len(t) == 0 {
		return t2, nil
	}
	t1, err := hexStrToHexByte(timeStamp)
	if err != nil {
		return nil, err
	}
	t2 = appendStringToGivenLen(t1, ocraSuiteTimeStampLengthB, dataInputAppendToken, appendToLeft)
	logger.Info.Println("Timestamp calculations: in command:", dataInput, ", The original timeSTamp:",
		timeStamp, ", The new timeStamp is:", t2, ", len:", len(t2))
	return t2, nil
}