/*
 * Copyright (c) 2012-2020 MIRACL UK Ltd.
 *
 * This file is part of MIRACL Core
 * (see https://github.com/miracl/core).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Implementation of the Secure Hashing Algorithm (SHA-256)
 *
 * Generates a 256 bit message digest. It should be impossible to come
 * come up with two messages that hash to the same value ("collision free").
 *
 * For use with byte-oriented messages only.
 */

package core

const MC_SHA2 int = 2
const MC_SHA3 int = 3

/* Convert Integer to n-byte array */
func InttoBytes(n int, len int) []byte {
	var b []byte
	var i int
	for i = 0; i < len; i++ {
		b = append(b, 0)
	}
	i = len
	for n > 0 && i > 0 {
		i--
		b[i] = byte(n & 0xff)
		n /= 256
	}
	return b
}

/* general purpose hashing of Byte array|integer|Byte array. Output of length olen, padded with leading zeros if required */

func GPhashit(hash int, hlen int, olen int, zpad int, A []byte, n int32, B []byte) []byte {
	var R []byte
	if hash == MC_SHA2 {
		if hlen == SHA256 {
			H := NewHASH256()
			for i := 0; i < zpad; i++ {
				H.Process(0)
			}
			if A != nil {
				H.Process_array(A)
			}
			if n >= 0 {
				H.Process_num(int32(n))
			}
			if B != nil {
				H.Process_array(B)
			}
			R = H.Hash()
		}
		if hlen == SHA384 {
			H := NewHASH384()
			for i := 0; i < zpad; i++ {
				H.Process(0)
			}
			if A != nil {
				H.Process_array(A)
			}
			if n >= 0 {
				H.Process_num(int32(n))
			}
			if B != nil {
				H.Process_array(B)
			}
			R = H.Hash()
		}
		if hlen == SHA512 {
			H := NewHASH512()
			for i := 0; i < zpad; i++ {
				H.Process(0)
			}
			if A != nil {
				H.Process_array(A)
			}
			if n >= 0 {
				H.Process_num(int32(n))
			}
			if B != nil {
				H.Process_array(B)
			}
			R = H.Hash()
		}
	}
	if hash == MC_SHA3 {
		H := NewSHA3(hlen)
		for i := 0; i < zpad; i++ {
			H.Process(0)
		}
		if A != nil {
			H.Process_array(A)
		}
		if n >= 0 {
			H.Process_num(int32(n))
		}
		if B != nil {
			H.Process_array(B)
		}
		R = H.Hash()
	}

	if R == nil {
		return nil
	}

	if olen == 0 {
		return R
	}
	var W []byte
	for i := 0; i < olen; i++ {
		W = append(W, 0)
	}
	if olen <= hlen {
		for i := 0; i < olen; i++ {
			W[i] = R[i]
		}
	} else {
		for i := 0; i < hlen; i++ {
			W[i+olen-hlen] = R[i]
		}
		for i := 0; i < olen-hlen; i++ {
			W[i] = 0
		}
	}
	return W
}

/* Simple hashing of byte array */
func SPhashit(hash int, hlen int, A []byte) []byte {
	return GPhashit(hash, hlen, 0, 0, A, -1, nil)
}

/* Key Derivation Function */
/* Input octet Z */
/* Output key of length olen */

func KDF2(hash int, sha int, Z []byte, P []byte, olen int) []byte {
	/* NOTE: the parameter olen is the length of the output k in bytes */
	hlen := sha
	var K []byte
	k := 0

	for i := 0; i < olen; i++ {
		K = append(K, 0)
	}

	cthreshold := olen / hlen
	if olen%hlen != 0 {
		cthreshold++
	}

	for counter := 1; counter <= cthreshold; counter++ {
		B := GPhashit(hash, sha, 0, 0, Z, int32(counter), P)
		if k+hlen > olen {
			for i := 0; i < olen%hlen; i++ {
				K[k] = B[i]
				k++
			}
		} else {
			for i := 0; i < hlen; i++ {
				K[k] = B[i]
				k++
			}
		}
	}
	return K
}

/* Password based Key Derivation Function */
/* Input password p, salt s, and repeat count */
/* Output key of length olen */
func PBKDF2(hash int, sha int, Pass []byte, Salt []byte, rep int, olen int) []byte {
	d := olen / sha
	if olen%sha != 0 {
		d++
	}

	var F []byte
	var U []byte
	var S []byte
	var K []byte

	for i := 0; i < sha; i++ {
		F = append(F, 0)
		U = append(U, 0)
	}

	for i := 1; i <= d; i++ {
		for j := 0; j < len(Salt); j++ {
			S = append(S, Salt[j])
		}
		N := InttoBytes(i, 4)
		for j := 0; j < 4; j++ {
			S = append(S, N[j])
		}

		HMAC(MC_SHA2, sha, F[:], sha, S, Pass)

		for j := 0; j < sha; j++ {
			U[j] = F[j]
		}
		for j := 2; j <= rep; j++ {
			HMAC(MC_SHA2, sha, U[:], sha, U[:], Pass)
			for k := 0; k < sha; k++ {
				F[k] ^= U[k]
			}
		}
		for j := 0; j < sha; j++ {
			K = append(K, F[j])
		}
	}
	var key []byte
	for i := 0; i < olen; i++ {
		key = append(key, K[i])
	}
	return key
}

func blksize(hash int, sha int) int {
	b := 0
	if hash == MC_SHA2 {
		b = 64
		if sha > 32 {
			b = 128
		}
	}
	if hash == MC_SHA3 {
		b = 200 - 2*sha
	}
	return b
}

/* Calculate HMAC of m using key k. HMAC is tag of length olen (which is length of tag) */
func HMAC(hash int, sha int, tag []byte, olen int, K []byte, M []byte) int {
	/* Input is from an octet m        *
	* olen is requested output length in bytes. k is the key  *
	* The output is the calculated tag */
	var B []byte

	b := blksize(hash, sha)
	if b == 0 {
		return 0
	}

	var K0 [200]byte
	//olen := len(tag)

	for i := 0; i < b; i++ {
		K0[i] = 0
	}

	if len(K) > b {
		B = SPhashit(hash, sha, K)
		for i := 0; i < sha; i++ {
			K0[i] = B[i]
		}
	} else {
		for i := 0; i < len(K); i++ {
			K0[i] = K[i]
		}
	}

	for i := 0; i < b; i++ {
		K0[i] ^= 0x36
	}
	B = GPhashit(hash, sha, 0, 0, K0[0:b], -1, M)

	for i := 0; i < b; i++ {
		K0[i] ^= 0x6a
	}
	B = GPhashit(hash, sha, olen, 0, K0[0:b], -1, B)

	for i := 0; i < olen; i++ {
		tag[i] = B[i]
	}

	return 1
}

func HKDF_Extract(hash int, hlen int, SALT []byte, IKM []byte) []byte {
	var PRK []byte
	for i := 0; i < hlen; i++ {
		PRK = append(PRK, 0)
	}
	if SALT == nil {
		var H []byte
		for i := 0; i < hlen; i++ {
			H = append(H, 0)
		}
		HMAC(hash, hlen, PRK, hlen, H, IKM)
	} else {
		HMAC(hash, hlen, PRK, hlen, SALT, IKM)
	}
	return PRK
}

func HKDF_Expand(hash int, hlen int, olen int, PRK []byte, INFO []byte) []byte {
	n := olen / hlen
	flen := olen % hlen

	var OKM []byte
	var T []byte
	var K [64]byte

	for i := 1; i <= n; i++ {
		for j := 0; j < len(INFO); j++ {
			T = append(T, INFO[j])
		}
		T = append(T, byte(i))
		HMAC(hash, hlen, K[:], hlen, PRK, T)
		T = nil
		for j := 0; j < hlen; j++ {
			OKM = append(OKM, K[j])
			T = append(T, K[j])
		}
	}
	if flen > 0 {
		for j := 0; j < len(INFO); j++ {
			T = append(T, INFO[j])
		}
		T = append(T, byte(n+1))
		HMAC(hash, hlen, K[:], flen, PRK, T)
		for j := 0; j < flen; j++ {
			OKM = append(OKM, K[j])
		}
	}
	return OKM
}

func ceil(a int, b int) int {
	return (((a)-1)/(b) + 1)
}

func XOF_Expand(hlen int, olen int, DST []byte, MSG []byte) []byte {
	var OKM = make([]byte, olen)
	H := NewSHA3(hlen)
	for i := 0; i < len(MSG); i++ {
		H.Process(MSG[i])
	}
	H.Process(byte((olen >> 8) & 0xff))
	H.Process(byte(olen & 0xff))

	for i := 0; i < len(DST); i++ {
		H.Process(DST[i])
	}
	H.Process(byte(len(DST) & 0xff))

	H.Shake(OKM[:], olen)
	return OKM
}

func xmd_Expand_Short_DST(hash int, hlen int, olen int, DST []byte, MSG []byte) []byte {
	var OKM = make([]byte, olen)
	var TMP = make([]byte, len(DST)+4)

	ell := ceil(olen, hlen)
	blk := blksize(hash, hlen)
	TMP[0] = byte((olen >> 8) & 0xff)
	TMP[1] = byte(olen & 0xff)
	TMP[2] = byte(0)

	for j := 0; j < len(DST); j++ {
		TMP[3+j] = DST[j]
	}
	TMP[3+len(DST)] = byte(len(DST) & 0xff)
	var H0 = GPhashit(hash, hlen, 0, blk, MSG, -1, TMP)

	var H1 = make([]byte, hlen)
	var TMP2 = make([]byte, len(DST)+2)

	k := 0
	for i := 1; i <= ell; i++ {
		for j := 0; j < hlen; j++ {
			H1[j] ^= H0[j]
		}
		TMP2[0] = byte(i)

		for j := 0; j < len(DST); j++ {
			TMP2[1+j] = DST[j]
		}
		TMP2[1+len(DST)] = byte(len(DST) & 0xff)

		H1 = GPhashit(hash, hlen, 0, 0, H1, -1, TMP2)
		for j := 0; j < hlen && k < olen; j++ {
			OKM[k] = H1[j]
			k++
		}
	}
	return OKM
}

func XMD_Expand(hash int, hlen int, olen int, DST []byte, MSG []byte) []byte {
	var R []byte
	OS := []byte("H2C-OVERSIZE-DST-")
	if len(DST)>=256 {
		W := GPhashit(hash, hlen, 0, 0, OS, -1, DST)
		R=xmd_Expand_Short_DST(hash,hlen,olen,W,MSG)
	} else {
		R=xmd_Expand_Short_DST(hash,hlen,olen,DST,MSG)
	}
	return R;
}

/* Mask Generation Function */

func MGF1(sha int, Z []byte, olen int, K []byte) {
	hlen := sha

	var k int = 0
	for i := 0; i < len(K); i++ {
		K[i] = 0
	}

	cthreshold := olen / hlen
	if olen%hlen != 0 {
		cthreshold++
	}
	for counter := 0; counter < cthreshold; counter++ {
		B := GPhashit(MC_SHA2, sha, 0, 0, Z, int32(counter), nil)
		//B := hashit(sha, Z, counter)

		if k+hlen > olen {
			for i := 0; i < olen%hlen; i++ {
				K[k] = B[i]
				k++
			}
		} else {
			for i := 0; i < hlen; i++ {
				K[k] = B[i]
				k++
			}
		}
	}
}

func MGF1XOR(sha int, Z []byte, olen int, K []byte) {
	hlen := sha

	var k int = 0

	cthreshold := olen / hlen
	if olen%hlen != 0 {
		cthreshold++
	}
	for counter := 0; counter < cthreshold; counter++ {
		B := GPhashit(MC_SHA2, sha, 0, 0, Z, int32(counter), nil)
		//B := hashit(sha, Z, counter)

		if k+hlen > olen {
			for i := 0; i < olen%hlen; i++ {
				K[k] ^= B[i]
				k++
			}
		} else {
			for i := 0; i < hlen; i++ {
				K[k] ^= B[i]
				k++
			}
		}
	}
}

/* SHAXXX identifier strings */
var SHA256ID = [...]byte{0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}
var SHA384ID = [...]byte{0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}
var SHA512ID = [...]byte{0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}

func RSA_PKCS15(sha int, m []byte, w []byte, RFS int) bool {
	olen := RFS
	hlen := sha
	idlen := 19

	if olen < idlen+hlen+10 {
		return false
	}
	H := SPhashit(MC_SHA2, sha, m)
	//H := hashit(sha, m, -1)

	for i := 0; i < len(w); i++ {
		w[i] = 0
	}
	i := 0
	w[i] = 0
	i++
	w[i] = 1
	i++
	for j := 0; j < olen-idlen-hlen-3; j++ {
		w[i] = 0xff
		i++
	}
	w[i] = 0
	i++

	if hlen == SHA256 {
		for j := 0; j < idlen; j++ {
			w[i] = SHA256ID[j]
			i++
		}
	}
	if hlen == SHA384 {
		for j := 0; j < idlen; j++ {
			w[i] = SHA384ID[j]
			i++
		}
	}
	if hlen == SHA512 {
		for j := 0; j < idlen; j++ {
			w[i] = SHA512ID[j]
			i++
		}
	}
	for j := 0; j < hlen; j++ {
		w[i] = H[j]
		i++
	}

	return true
}

/* SHAXXX identifier strings */
var SHA256IDb = [...]byte{0x30, 0x2f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x04, 0x20}
var SHA384IDb = [...]byte{0x30, 0x3f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x04, 0x30}
var SHA512IDb = [...]byte{0x30, 0x4f, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x04, 0x40}

func RSA_PKCS15b(sha int, m []byte, w []byte, RFS int) bool {
	olen := RFS
	hlen := sha
	idlen := 17

	if olen < idlen+hlen+10 {
		return false
	}
	H := SPhashit(MC_SHA2,sha,m)
	//H := hashit(sha, m, -1)

	for i := 0; i < len(w); i++ {
		w[i] = 0
	}
	i := 0
	w[i] = 0
	i++
	w[i] = 1
	i++
	for j := 0; j < olen-idlen-hlen-3; j++ {
		w[i] = 0xff
		i++
	}
	w[i] = 0
	i++

	if hlen == SHA256 {
		for j := 0; j < idlen; j++ {
			w[i] = SHA256IDb[j]
			i++
		}
	}
	if hlen == SHA384 {
		for j := 0; j < idlen; j++ {
			w[i] = SHA384IDb[j]
			i++
		}
	}
	if hlen == SHA512 {
		for j := 0; j < idlen; j++ {
			w[i] = SHA512IDb[j]
			i++
		}
	}
	for j := 0; j < hlen; j++ {
		w[i] = H[j]
		i++
	}
	return true
}


func RSA_PSS_ENCODE(sha int, m []byte, rng *RAND, RFS int) []byte {
	emlen := RFS
	embits := 8*emlen - 1

	hlen := sha
	SALT := make([]byte, hlen)
	for i := 0; i < hlen; i++ {
		SALT[i] = rng.GetByte()
	}
	mask := byte(0xff >> (8*emlen - embits))

	H := SPhashit(MC_SHA2, sha, m)
	if emlen < hlen+hlen+2 {
		return nil
	}

	MD := make([]byte, 8+hlen+hlen)
	for i := 0; i < 8; i++ {
		MD[i] = 0
	}
	for i := 0; i < hlen; i++ {
		MD[8+i] = H[i]
	}
	for i := 0; i < hlen; i++ {
		MD[8+hlen+i] = SALT[i]
	}
	H = SPhashit(MC_SHA2, sha, MD)
	f := make([]byte, RFS)
	for i := 0; i < emlen-hlen-hlen-2; i++ {
		f[i] = 0
	}
	f[emlen-hlen-hlen-2] = 0x1
	for i := 0; i < hlen; i++ {
		f[emlen+i-hlen-hlen-1] = SALT[i]
	}

	MGF1XOR(sha, H, emlen-hlen-1, f)
	f[0] &= mask
	for i := 0; i < hlen; i++ {
		f[emlen+i-hlen-1] = H[i]
	}
	f[emlen-1] = byte(0xbc)
	return f
}

func RSA_PSS_VERIFY(sha int, m []byte, f []byte) bool {
	emlen := len(f)
	embits := 8*emlen - 1
	hlen := sha
	SALT := make([]byte, hlen)
	mask := byte(0xff >> (8*emlen - embits))

	HMASK := SPhashit(MC_SHA2, sha, m)
	if emlen < hlen+hlen+2 {
		return false
	}
	if f[emlen-1] != byte(0xbc) {
		return false
	}
	if (f[0] & (^mask)) != 0 {
		return false
	}
	DB := make([]byte, emlen-hlen-1)
	for i := 0; i < emlen-hlen-1; i++ {
		DB[i] = f[i]
	}
	H := make([]byte, hlen)
	for i := 0; i < hlen; i++ {
		H[i] = f[emlen+i-hlen-1]
	}
	MGF1XOR(sha, H, emlen-hlen-1, DB)
	DB[0] &= mask
	k := byte(0)
	for i := 0; i < emlen-hlen-hlen-2; i++ {
		k |= DB[i]
	}
	if k != 0 {
		return false
	}
	if DB[emlen-hlen-hlen-2] != 0x01 {
		return false
	}

	for i := 0; i < hlen; i++ {
		SALT[i] = DB[emlen+i-hlen-hlen-1]
	}
	MD := make([]byte, 8+hlen+hlen)
	for i := 0; i < 8; i++ {
		MD[i] = 0
	}
	for i := 0; i < hlen; i++ {
		MD[8+i] = HMASK[i]
	}
	for i := 0; i < hlen; i++ {
		MD[8+hlen+i] = SALT[i]
	}
	HMASK = SPhashit(MC_SHA2, sha, MD)
	k = 0
	for i := 0; i < hlen; i++ {
		k |= (H[i] - HMASK[i])
	}
	if k != 0 {
		return false
	}
	return true
}

/* OAEP Message Encoding for Encryption */
func RSA_OAEP_ENCODE(sha int, m []byte, rng *RAND, p []byte, RFS int) []byte {
	olen := RFS - 1
	mlen := len(m)
	//var f [RFS]byte
	f := make([]byte, RFS)

	hlen := sha

	SEED := make([]byte, hlen)

	seedlen := hlen
	if mlen > olen-hlen-seedlen-1 {
		return nil
	}

	DBMASK := make([]byte, olen-seedlen)

	h := SPhashit(MC_SHA2, sha, p)
	//h := hashit(sha, p, -1)

	for i := 0; i < hlen; i++ {
		f[i] = h[i]
	}

	slen := olen - mlen - hlen - seedlen - 1

	for i := 0; i < slen; i++ {
		f[hlen+i] = 0
	}
	f[hlen+slen] = 1
	for i := 0; i < mlen; i++ {
		f[hlen+slen+1+i] = m[i]
	}

	for i := 0; i < seedlen; i++ {
		SEED[i] = rng.GetByte()
	}
	MGF1(sha, SEED, olen-seedlen, DBMASK)

	for i := 0; i < olen-seedlen; i++ {
		DBMASK[i] ^= f[i]
	}

	MGF1(sha, DBMASK, seedlen, f[:])

	for i := 0; i < seedlen; i++ {
		f[i] ^= SEED[i]
	}

	for i := 0; i < olen-seedlen; i++ {
		f[i+seedlen] = DBMASK[i]
	}

	/* pad to length RFS */
	d := 1
	for i := RFS - 1; i >= d; i-- {
		f[i] = f[i-d]
	}
	for i := d - 1; i >= 0; i-- {
		f[i] = 0
	}
	return f[:]
}

/* OAEP Message Decoding for Decryption */
func RSA_OAEP_DECODE(sha int, p []byte, f []byte, RFS int) []byte {
	olen := RFS - 1

	hlen := sha
	SEED := make([]byte, hlen)
	seedlen := hlen
	CHASH := make([]byte, hlen)

	if olen < seedlen+hlen+1 {
		return nil
	}
	DBMASK := make([]byte, olen-seedlen)
	for i := 0; i < olen-seedlen; i++ {
		DBMASK[i] = 0
	}

	if len(f) < RFS {
		d := RFS - len(f)
		for i := RFS - 1; i >= d; i-- {
			f[i] = f[i-d]
		}
		for i := d - 1; i >= 0; i-- {
			f[i] = 0
		}
	}

	h := SPhashit(MC_SHA2, sha, p)
	//h := hashit(sha, p, -1)
	for i := 0; i < hlen; i++ {
		CHASH[i] = h[i]
	}

	x := f[0]

	for i := seedlen; i < olen; i++ {
		DBMASK[i-seedlen] = f[i+1]
	}

	MGF1(sha, DBMASK, seedlen, SEED)
	for i := 0; i < seedlen; i++ {
		SEED[i] ^= f[i+1]
	}
	MGF1(sha, SEED, olen-seedlen, f)
	for i := 0; i < olen-seedlen; i++ {
		DBMASK[i] ^= f[i]
	}

	comp := 0
	for i := 0; i < hlen; i++ {
		comp |= int(CHASH[i] ^ DBMASK[i])
		//if CHASH[i] != DBMASK[i] {
		//	comp = false
		//}
	}
	m:=olen-seedlen-hlen
	for i := 0; i < m; i++ {
		DBMASK[i] = DBMASK[i+hlen]
	}

	for i := 0; i < hlen; i++ {
		SEED[i] = 0
		CHASH[i] = 0
	}

	k:=0
	t:=0
	for i:=0;i<m; i++ {
		if t==0 && DBMASK[i]!=0 {
			k=i
			t=int(DBMASK[i])
		}
	}
/*
	var k int
	for k = 0; ; k++ {
		if k >= m {
			return nil
		}
		if DBMASK[k] != 0 {
			break
		}
	}
	t := DBMASK[k] */

	if comp!=0 || x != 0 || t != 0x01 {
		for i := 0; i < olen-seedlen; i++ {
			DBMASK[i] = 0
		}
		return nil
	}

	var r = make([]byte, m-k-1)

	for i := 0; i < m-k-1; i++ {
		r[i] = DBMASK[i+k+1]
	}

	for i := 0; i < olen-seedlen; i++ {
		DBMASK[i] = 0
	}

	return r
}

/*


	MSG := []byte("abc")
	DST := []byte("P256_XMD:SHA-256_SSWU_RO_TESTGEN")

	OKM := core.XOF_Expand(core.SHA3_SHAKE128,48,DST,MSG)
	fmt.Printf("OKM= "); printBinary(OKM[:])

	OKM = core.XMD_Expand(core.MC_SHA2,32,48,DST,MSG)
	fmt.Printf("OKM= "); printBinary(OKM[:])



func main() {
	var ikm []byte
	var salt []byte
	var info []byte

	for i:=0;i<22;i++ {ikm=append(ikm,0x0b)}
	for i:=0;i<13;i++ {salt=append(salt,byte(i))}
	for i:=0;i<10;i++ {info=append(info,byte(0xf0+i))}

	prk:=core.HKDF_Extract(core.MC_SHA2,32,salt,ikm)
	fmt.Printf("PRK= ")
	for i := 0; i < len(prk); i++ {
		fmt.Printf("%02x", prk[i])
	}

	okm:=core.HKDF_Expand(core.MC_SHA2,32,42,prk,info)
	fmt.Printf("\nOKM= ")
	for i := 0; i < len(okm); i++ {
		fmt.Printf("%02x", okm[i])
	}

}
*/
