Просмотр исходного кода

aes256-cts-hmac-sha1-96 implementation

Jonathan Turner 9 лет назад
Родитель
Сommit
6bac6ade24

+ 1 - 2
krb5crypto/EncryptionEngine.go

@@ -47,7 +47,7 @@ func deriveRandom(key, usage []byte, n, k int, encrypt encryptFunc) ([]byte, err
 	DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...)*/
 	K, err := encrypt(key, nFoldUsage)
 	if err != nil {
-		return out, nil
+		return out, err
 	}
 	for i := copy(out, K); i < len(out); {
 		K, _ = encrypt(key, K)
@@ -56,7 +56,6 @@ func deriveRandom(key, usage []byte, n, k int, encrypt encryptFunc) ([]byte, err
 	return out, nil
 }
 
-
 func pkcs7Pad(b []byte, m int) ([]byte, error) {
 	if m <= 0 {
 		return nil, errors.New("Invalid message block size when padding")

+ 16 - 25
krb5crypto/aes256-cts-hmac-sha1-96.go

@@ -14,13 +14,6 @@ import (
 	"strings"
 )
 
-const (
-	CipherKeyLength = 256 // AES256
-	HMACKeyLength   = 96  // SHA96
-	KeySize         = 352 // CipherKeyLength + HMACKeyLength
-	NonceSize       = aes.BlockSize
-)
-
 //+--------------------------------------------------------------------+
 //|               protocol key format        128- or 256-bit string    |
 //|                                                                    |
@@ -66,6 +59,10 @@ const (
 //|    hmac-sha1-96-aes256                16                   96      |
 //+--------------------------------------------------------------------+
 
+const (
+	s2kParamsZero = 4294967296
+)
+
 type Aes256CtsHmacSha196 struct {
 }
 
@@ -113,7 +110,7 @@ func (e *Aes256CtsHmacSha196) StringToKey(secret string, salt string, s2kparams
 	//be performed is 4,294,967,296 (2**32).
 	var i int
 	if s2kparams == "00 00 00 00" {
-		i = 4294967296
+		i = s2kParamsZero
 	} else {
 		s := strings.Replace(s2kparams, " ", "", -1)
 		if len(s) != 8 {
@@ -126,7 +123,7 @@ func (e *Aes256CtsHmacSha196) StringToKey(secret string, salt string, s2kparams
 		buf := bytes.NewBuffer(b)
 		binary.Read(buf, binary.BigEndian, &i)
 		if i == 0 {
-			i = 4294967296
+			i = s2kParamsZero
 		}
 	}
 
@@ -160,38 +157,32 @@ func (e *Aes256CtsHmacSha196) DeriveKey(protocolKey, usage []byte) ([]byte, erro
 	return e.RandomToKey(r), nil
 }
 
-func (e *Aes256CtsHmacSha196) Encrypt(key, message []byte) (ct []byte, err error) {
-	if len(key) != KeySize {
-		err = fmt.Errorf("Incorrect keysize: expected: %v actual: %v", KeySize, len(key))
-		return
+func (e *Aes256CtsHmacSha196) Encrypt(key, message []byte) ([]byte, error) {
+	if len(key) != e.GetKeyByteSize() {
+		return nil, fmt.Errorf("Incorrect keysize: expected: %v actual: %v", e.GetKeySeedBitLength(), len(key))
 	}
 	if len(message)%aes.BlockSize != 0 {
-		err = errors.New("Plaintext is not a multiple of the block size. Padding may be needed.")
-		return
+		message, _ = pkcs7Pad(message, e.GetMessageBlockByteSize())
 	}
 
 	block, err := aes.NewCipher(key)
 	if err != nil {
-		err = fmt.Errorf("Error creating cipher: %v", err)
-		return
+		return nil, fmt.Errorf("Error creating cipher: %v", err)
 	}
 
 	//RFC 3961: initial cipher state      All bits zero
-	iv := make([]byte, NonceSize)
+	iv := make([]byte, e.GetConfounderByteSize())
 	//_, err = rand.Read(iv) //Not needed as all bits need to be zero
-	if err != nil {
-		err = fmt.Errorf("Error creating random nonce/initial state: %v", err)
-		return
-	}
 
+	ct := make([]byte, len(message))
 	mode := cipher.NewCBCEncrypter(block, iv)
 	mode.CryptBlocks(ct, message)
-	return
+	return ct, nil
 }
 
 func (e *Aes256CtsHmacSha196) Decrypt(key, ciphertext []byte) (message []byte, err error) {
-	if len(key) != KeySize {
-		err = fmt.Errorf("Incorrect keysize: expected: %v actual: %v", KeySize, len(key))
+	if len(key) != e.GetKeySeedBitLength() {
+		err = fmt.Errorf("Incorrect keysize: expected: %v actual: %v", e.GetKeySeedBitLength(), len(key))
 		return
 	}
 	if len(ciphertext) < aes.BlockSize || len(ciphertext)%aes.BlockSize != 0 {

+ 20 - 3
krb5crypto/aes256-cts-hmac-sha1-96_test.go

@@ -6,18 +6,35 @@ import (
 	"testing"
 )
 
-func TestAes256CtsHmacSha196_StringToPBKDF2(t *testing.T) {
+func TestAes256CtsHmacSha196_StringToKey(t *testing.T) {
 	// Test vectors from RFC 3962 Appendix B
+	b, _ := hex.DecodeString("1234567878563412")
+	s := string(b)
+	b, _ = hex.DecodeString("f09d849e")
+	s2 := string(b)
 	var tests = []struct {
 		iterations int
 		phrase     string
 		salt       string
 		pbkdf2     string
+		key        string
 	}{
-		{1, "password", "ATHENA.MIT.EDUraeburn", "cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837"},
+		{1, "password", "ATHENA.MIT.EDUraeburn", "cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837", "fe697b52bc0d3ce14432ba036a92e65bbb52280990a2fa27883998d72af30161"},
+		{2, "password", "ATHENA.MIT.EDUraeburn", "01dbee7f4a9e243e988b62c73cda935da05378b93244ec8f48a99e61ad799d86", "a2e16d16b36069c135d5e9d2e25f896102685618b95914b467c67622225824ff"},
+		{1200, "password", "ATHENA.MIT.EDUraeburn", "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddbc5e5142f708a31e2e62b1e13", "55a6ac740ad17b4846941051e1e8b0a7548d93b0ab30a8bc3ff16280382b8c2a"},
+		{5, "password", s, "d1daa78615f287e6a1c8b120d7062a493f98d203e6be49a6adf4fa574b6e64ee", "97a4e786be20d81a382d5ebc96d5909cabcdadc87ca48f574504159f16c36e31"},
+		{1200, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "pass phrase equals block size", "139c30c0966bc32ba55fdbf212530ac9c5ec59f1a452f5cc9ad940fea0598ed1", "89adee3608db8bc71f1bfbfe459486b05618b70cbae22092534e56c553ba4b34"},
+		{1200, "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", "pass phrase exceeds block size", "9ccad6d468770cd51b10e6a68721be611a8b4d282601db3b36be9246915ec82a", "d78c5c9cb872a8c9dad4697f0bb5b2d21496c82beb2caeda2112fceea057401b"},
+		{50, s2, "EXAMPLE.COMpianist", "6b9cf26d45455a43a5b8bb276a403b39e7fe37a0c41e02c281ff3069e1e94f52", "4b6d9839f84406df1f09cc166db4b83c571848b784a3d6bdc346589a3e393f9e"},
 	}
-	for _, test := range tests {
+	for i, test := range tests {
 		var e Aes256CtsHmacSha196
 		assert.Equal(t, test.pbkdf2, hex.EncodeToString(e.StringToPBKDF2(test.phrase, test.salt, test.iterations)), "PBKDF2 not as expected")
+		k, err := e.StringToKeyIter(test.phrase, test.salt, test.iterations)
+		if err != nil {
+			t.Errorf("Error in processing string to key for test %d: %v", i, err)
+		}
+		assert.Equal(t, test.key, hex.EncodeToString(k), "String to Key not as expected")
+
 	}
 }