Explorar el Código

aes string to key work

Jonathan Turner hace 9 años
padre
commit
584ab80502

+ 142 - 10
krb5crypto/aes256-cts-hmac-sha1-96.go

@@ -1,10 +1,17 @@
 package krb5crypto
 
 import (
+	"bytes"
 	"crypto/aes"
 	"crypto/cipher"
+	"crypto/sha1"
+	"encoding/binary"
+	"encoding/hex"
 	"errors"
 	"fmt"
+	"golang.org/x/crypto/pbkdf2"
+	"hash"
+	"strings"
 )
 
 const (
@@ -14,21 +21,146 @@ const (
 	NonceSize       = aes.BlockSize
 )
 
-func StringToKey(secret string, salt string, s2kparams []byte) (protocolKey []byte) {
-	return
+//+--------------------------------------------------------------------+
+//|               protocol key format        128- or 256-bit string    |
+//|                                                                    |
+//|            string-to-key function        PBKDF2+DK with variable   |
+//|                                          iteration count (see      |
+//|                                          above)                    |
+//|                                                                    |
+//|  default string-to-key parameters        00 00 10 00               |
+//|                                                                    |
+//|        key-generation seed length        key size                  |
+//|                                                                    |
+//|            random-to-key function        identity function         |
+//|                                                                    |
+//|                  hash function, H        SHA-1                     |
+//|                                                                    |
+//|               HMAC output size, h        12 octets (96 bits)       |
+//|                                                                    |
+//|             message block size, m        1 octet                   |
+//|                                                                    |
+//|  encryption/decryption functions,        AES in CBC-CTS mode       |
+//|  E and D                                 (cipher block size 16     |
+//|                                          octets), with next-to-    |
+//|                                          last block (last block    |
+//|                                          if only one) as CBC-style |
+//|                                          ivec                      |
+//+--------------------------------------------------------------------+
+//
+//+--------------------------------------------------------------------+
+//|                         encryption types                           |
+//+--------------------------------------------------------------------+
+//|         type name                  etype value          key size   |
+//+--------------------------------------------------------------------+
+//|   aes128-cts-hmac-sha1-96              17                 128      |
+//|   aes256-cts-hmac-sha1-96              18                 256      |
+//+--------------------------------------------------------------------+
+//
+//+--------------------------------------------------------------------+
+//|                          checksum types                            |
+//+--------------------------------------------------------------------+
+//|        type name                 sumtype value           length    |
+//+--------------------------------------------------------------------+
+//|    hmac-sha1-96-aes128                15                   96      |
+//|    hmac-sha1-96-aes256                16                   96      |
+//+--------------------------------------------------------------------+
+
+type Aes256CtsHmacSha196 struct {
 }
 
-func RandomToKey(b []byte) (protocolKey []byte) {
-	return
+func (e *Aes256CtsHmacSha196) GetETypeID() int {
+	return 18
+}
+
+func (e *Aes256CtsHmacSha196) GetKeyByteSize() int {
+	return 256 / 8
+}
+
+func (e *Aes256CtsHmacSha196) GetKeySeedBitLength() int {
+	return e.GetKeyByteSize() * 8
+}
+
+func (e *Aes256CtsHmacSha196) GetHash() hash.Hash {
+	return sha1.New()
+}
+
+func (e *Aes256CtsHmacSha196) GetMessageBlockByteSize() int {
+	return 1
+}
+
+func (e *Aes256CtsHmacSha196) GetDefaultStringToKeyParams() string {
+	return "00 00 10 00"
+}
+
+func (e *Aes256CtsHmacSha196) GetConfounderByteSize() int {
+	return aes.BlockSize
+}
+
+func (e *Aes256CtsHmacSha196) GetHMACBitLength() int {
+	return 96
 }
 
-func DeriveKey(protocolKey, usage []byte) (specificKey []byte) {
-	e := Encrypt
-	r, _ := deriveRandom(protocolKey, usage, aes.BlockSize * 8, CipherKeyLength, e)
-	return r
+func (e *Aes256CtsHmacSha196) GetCypherBlockBitLength() int {
+	return aes.BlockSize * 8
+}
+
+func (e *Aes256CtsHmacSha196) StringToKey(secret string, salt string, s2kparams string) ([]byte, error) {
+	//process s2kparams string
+	//The parameter string is four octets indicating an unsigned
+	//number in big-endian order.  This is the number of iterations to be
+	//performed.  If the value is 00 00 00 00, the number of iterations to
+	//be performed is 4,294,967,296 (2**32).
+	var i int
+	if s2kparams == "00 00 00 00" {
+		i = 4294967296
+	} else {
+		s := strings.Replace(s2kparams, " ", "", -1)
+		if len(s) != 8 {
+			return nil, errors.New("Invalid s2kparams")
+		}
+		b, err := hex.DecodeString(s)
+		if err != nil {
+			return nil, errors.New("Invalid s2kparams")
+		}
+		buf := bytes.NewBuffer(b)
+		binary.Read(buf, binary.BigEndian, &i)
+		if i == 0 {
+			i = 4294967296
+		}
+	}
+
+	return e.StringToKeyIter(secret, salt, i)
+}
+
+func (e *Aes256CtsHmacSha196) StringToPBKDF2(secret string, salt string, iterations int) []byte {
+	return pbkdf2.Key([]byte(secret), []byte(salt), iterations, e.GetKeyByteSize(), sha1.New)
+}
+
+func (e *Aes256CtsHmacSha196) StringToKeyIter(secret string, salt string, iterations int) ([]byte, error) {
+	tkey := e.RandomToKey(e.StringToPBKDF2(secret, salt, iterations))
+	key, err := e.DeriveKey(tkey, []byte("kerberos"))
+	return key, err
+}
+
+func (e *Aes256CtsHmacSha196) RandomToKey(b []byte) []byte {
+	return b
+}
+
+func (e *Aes256CtsHmacSha196) DeriveRandom(protocolKey, usage []byte) ([]byte, error) {
+	r, err := deriveRandom(protocolKey, usage, e.GetCypherBlockBitLength(), e.GetKeySeedBitLength(), e.Encrypt)
+	return r, err
+}
+
+func (e *Aes256CtsHmacSha196) DeriveKey(protocolKey, usage []byte) ([]byte, error) {
+	r, err := e.DeriveRandom(protocolKey, usage)
+	if err != nil {
+		return nil, err
+	}
+	return e.RandomToKey(r), nil
 }
 
-func Encrypt(key, message []byte) (ct []byte, err error) {
+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
@@ -57,7 +189,7 @@ func Encrypt(key, message []byte) (ct []byte, err error) {
 	return
 }
 
-func Decrypt(key, ciphertext []byte) (message []byte, err error) {
+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))
 		return

+ 23 - 0
krb5crypto/aes256-cts-hmac-sha1-96_test.go

@@ -0,0 +1,23 @@
+package krb5crypto
+
+import (
+	"encoding/hex"
+	"github.com/stretchr/testify/assert"
+	"testing"
+)
+
+func TestAes256CtsHmacSha196_StringToPBKDF2(t *testing.T) {
+	// Test vectors from RFC 3962 Appendix B
+	var tests = []struct {
+		iterations int
+		phrase     string
+		salt       string
+		pbkdf2     string
+	}{
+		{1, "password", "ATHENA.MIT.EDUraeburn", "cdedb5281bb2f801565a1122b25635150ad1f7a04bb9f3a333ecc0e2e1f70837"},
+	}
+	for _, 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")
+	}
+}

+ 7 - 9
krb5crypto/des3-cbc-sha1-kd.go

@@ -1,17 +1,16 @@
 package krb5crypto
 
 import (
-	"crypto/des"
-	"fmt"
 	"crypto/cipher"
-	"errors"
+	"crypto/des"
 	"crypto/sha1"
+	"errors"
+	"fmt"
 	"hash"
 )
 
 //RFC: 3961 Section 6.3
 
-
 /*
                  des3-cbc-hmac-sha1-kd, hmac-sha1-des3-kd
               ------------------------------------------------
@@ -48,7 +47,6 @@ import (
    checksum type number of twelve (12)*/
 
 type Des3CbcSha1Kd struct {
-
 }
 
 func (e *Des3CbcSha1Kd) GetETypeID() int {
@@ -107,7 +105,7 @@ func (e *Des3CbcSha1Kd) DeriveKey(protocolKey, usage []byte) ([]byte, error) {
 	if err != nil {
 		return nil, err
 	}
-	return RandomToKey(r), nil
+	return e.RandomToKey(r), nil
 }
 
 func (e *Des3CbcSha1Kd) Encrypt(key, message []byte) ([]byte, error) {
@@ -115,7 +113,7 @@ func (e *Des3CbcSha1Kd) Encrypt(key, message []byte) ([]byte, error) {
 		return nil, fmt.Errorf("Incorrect keysize: expected: %v actual: %v", e.GetKeySeedBitLength(), len(key))
 
 	}
-	if len(message) % e.GetMessageBlockByteSize() != 0 {
+	if len(message)%e.GetMessageBlockByteSize() != 0 {
 		message, _ = pkcs7Pad(message, e.GetMessageBlockByteSize())
 	}
 
@@ -141,7 +139,7 @@ func (e *Des3CbcSha1Kd) Decrypt(key, ciphertext []byte) (message []byte, err err
 		return
 	}
 
-	if len(ciphertext) < des.BlockSize || len(ciphertext) % des.BlockSize != 0 {
+	if len(ciphertext) < des.BlockSize || len(ciphertext)%des.BlockSize != 0 {
 		err = errors.New("Ciphertext is not a multiple of the block size.")
 		return
 	}
@@ -162,4 +160,4 @@ func (e *Des3CbcSha1Kd) Decrypt(key, ciphertext []byte) (message []byte, err err
 		message = m
 	}
 	return
-}
+}