func KeyStretcher(cipherType string, hashType string, secret []byte) (StretchedKeys, StretchedKeys) {
	var cipherKeySize int
	var ivSize int
	switch cipherType {
	case "AES-128":
		ivSize = 16
		cipherKeySize = 16
	case "AES-256":
		ivSize = 16
		cipherKeySize = 32
	case "Blowfish":
		ivSize = 8
		// Note: 24 arbitrarily selected, needs more thought
		cipherKeySize = 32
	}

	hmacKeySize := 20

	seed := []byte("key expansion")

	result := make([]byte, 2*(ivSize+cipherKeySize+hmacKeySize))

	var h func() hash.Hash

	switch hashType {
	case "SHA1":
		h = sha1.New
	case "SHA256":
		h = sha256.New
	case "SHA512":
		h = sha512.New
	default:
		panic("Unrecognized hash function, programmer error?")
	}

	m := hmac.New(h, secret)
	// note: guaranteed to never return an error
	m.Write(seed)

	a := m.Sum(nil)

	j := 0
	for j < len(result) {
		m.Reset()

		// note: guaranteed to never return an error.
		m.Write(a)
		m.Write(seed)

		b := m.Sum(nil)

		todo := len(b)

		if j+todo > len(result) {
			todo = len(result) - j
		}

		copy(result[j:j+todo], b)

		j += todo

		m.Reset()

		// note: guaranteed to never return an error.
		m.Write(a)

		a = m.Sum(nil)
	}

	half := len(result) / 2
	r1 := result[:half]
	r2 := result[half:]

	var k1 StretchedKeys
	var k2 StretchedKeys

	k1.IV = r1[0:ivSize]
	k1.CipherKey = r1[ivSize : ivSize+cipherKeySize]
	k1.MacKey = r1[ivSize+cipherKeySize:]

	k2.IV = r2[0:ivSize]
	k2.CipherKey = r2[ivSize : ivSize+cipherKeySize]
	k2.MacKey = r2[ivSize+cipherKeySize:]

	return k1, k2
}
func KeyStretcher(cipherType string, hashType string, secret []byte) (StretchedKeys, StretchedKeys) {
	var cipherKeySize int
	var ivSize int
	switch cipherType {
	case "AES-128":
		ivSize = 16
		cipherKeySize = 16
	case "AES-256":
		ivSize = 16
		cipherKeySize = 32
	case "Blowfish":
		ivSize = 8
		
		cipherKeySize = 32
	}

	hmacKeySize := 20

	seed := []byte("key expansion")

	result := make([]byte, 2*(ivSize+cipherKeySize+hmacKeySize))

	var h func() hash.Hash

	switch hashType {
	case "SHA1":
		h = sha1.New
	case "SHA256":
		h = sha256.New
	case "SHA512":
		h = sha512.New
	default:
		panic("Unrecognized hash function, programmer error?")
	}

	m := hmac.New(h, secret)
	
	m.Write(seed)

	a := m.Sum(nil)

	j := 0
	for j < len(result) {
		m.Reset()

		
		m.Write(a)
		m.Write(seed)

		b := m.Sum(nil)

		todo := len(b)

		if j+todo > len(result) {
			todo = len(result) - j
		}

		copy(result[j:j+todo], b)

		j += todo

		m.Reset()

		
		m.Write(a)

		a = m.Sum(nil)
	}

	half := len(result) / 2
	r1 := result[:half]
	r2 := result[half:]

	var k1 StretchedKeys
	var k2 StretchedKeys

	k1.IV = r1[0:ivSize]
	k1.CipherKey = r1[ivSize : ivSize+cipherKeySize]
	k1.MacKey = r1[ivSize+cipherKeySize:]

	k2.IV = r2[0:ivSize]
	k2.CipherKey = r2[ivSize : ivSize+cipherKeySize]
	k2.MacKey = r2[ivSize+cipherKeySize:]

	return k1, k2
}
func KeyStretcher ( cipherType string , hashType string , secret [ ] byte ) ( StretchedKeys , StretchedKeys ) { var cipherKeySize int var ivSize int switch cipherType { case " " : ivSize = 16 cipherKeySize = 16 case " " : ivSize = 16 cipherKeySize = 32 case " " : ivSize = 8 // Note: 24 arbitrarily selected, needs more thought cipherKeySize = 32 } hmacKeySize := 20 seed := [ ] byte ( " " ) result := make ( [ ] byte , 2 * ( ivSize + cipherKeySize + hmacKeySize ) ) var h func ( ) hash . Hash switch hashType { case " " : h = sha1 . New case " " : h = sha256 . New case " " : h = sha512 . New default : panic ( " " ) } m := hmac . New ( h , secret ) // note: guaranteed to never return an error m . Write ( seed ) a := m . Sum ( nil ) j := 0 for j < len ( result ) { m . Reset ( ) // note: guaranteed to never return an error. m . Write ( a ) m . Write ( seed ) b := m . Sum ( nil ) todo := len ( b ) if j + todo > len ( result ) { todo = len ( result ) - j } copy ( result [ j : j + todo ] , b ) j += todo m . Reset ( ) // note: guaranteed to never return an error. m . Write ( a ) a = m . Sum ( nil ) } half := len ( result ) / 2 r1 := result [ : half ] r2 := result [ half : ] var k1 StretchedKeys var k2 StretchedKeys k1 . IV = r1 [ 0 : ivSize ] k1 . CipherKey = r1 [ ivSize : ivSize + cipherKeySize ] k1 . MacKey = r1 [ ivSize + cipherKeySize : ] k2 . IV = r2 [ 0 : ivSize ] k2 . CipherKey = r2 [ ivSize : ivSize + cipherKeySize ] k2 . MacKey = r2 [ ivSize + cipherKeySize : ] return k1 , k2 }
// KeyStretcher returns a set of keys for each party by stretching the shared key.
// (myIV, theirIV, myCipherKey, theirCipherKey, myMACKey, theirMACKey)
KeyStretcher returns a set of keys for each party by stretching the shared key . ( myIV theirIV myCipherKey theirCipherKey myMACKey theirMACKey )