Parcourir la source

import aescts

Jonathan Turner il y a 8 ans
Parent
commit
6a12ba7e99

+ 5 - 5
README.md

@@ -1,5 +1,5 @@
 # gokrb5
-[![GoDoc](https://godoc.org/github.com/jcmturner/gokrb5?status.svg)](https://godoc.org/github.com/jcmturner/gokrb5) [![Go Report Card](https://goreportcard.com/badge/github.com/jcmturner/gokrb5)](https://goreportcard.com/report/github.com/jcmturner/gokrb5)
+[![GoDoc](https://godoc.org/gopkg.in/jcmturner/gokrb5.v1?status.svg)](https://godoc.org/gopkg.in/jcmturner/gokrb5.v1) [![Go Report Card](https://goreportcard.com/badge/gopkg.in/jcmturner/gokrb5.v1)](https://goreportcard.com/report/gopkg.in/jcmturner/gokrb5.v1)
 
 To get the package, execute:
 ```
@@ -51,7 +51,7 @@ Currently the following is working/tested:
 The gokrb5 libraries use the same krb5.conf configuration file format as MIT Kerberos, described [here](https://web.mit.edu/kerberos/krb5-latest/doc/admin/conf_files/krb5_conf.html).
 Config instances can be created by loading from a file path or by passing a string, io.Reader or bufio.Scanner to the relevant method:
 ```go
-import "github.com/jcmturner/gokrb5/config"
+import "gopkg.in/jcmturner/gokrb5.v1/config"
 cfg, err := config.Load("/path/to/config/file")
 cfg, err := config.NewConfigFromString(krb5Str) //String must have appropriate newline separations
 cfg, err := config.NewConfigFromReader(reader)
@@ -60,7 +60,7 @@ cfg, err := config.NewConfigFromScanner(scanner)
 ### Keytab files
 Standard keytab files can be read from a file or from a slice of bytes:
 ```go
-import 	"github.com/jcmturner/gokrb5/keytab"
+import 	"gopkg.in/jcmturner/gokrb5.v1/keytab"
 ktFromFile, err := keytab.Load("/path/to/file.keytab")
 ktFromBytes, err := keytab.Parse(b)
 
@@ -71,7 +71,7 @@ ktFromBytes, err := keytab.Parse(b)
 ### Kerberos Client
 Create a client instance with either a password or a keytab:
 ```go
-import 	"github.com/jcmturner/gokrb5/client"
+import 	"gopkg.in/jcmturner/gokrb5.v1/client"
 cl := client.NewClientWithPassword("username", "REALM.COM", "password")
 cl := client.NewClientWithKeytab("username", "REALM.COM", kt)
 
@@ -179,7 +179,7 @@ if validuser, ok := ctx.Value(service.CTXKeyAuthenticated).(bool); ok && validus
 #### Generic Kerberised Service - Validating Client Details
 To validate the AP_REQ sent by the client on the service side call this method:
 ```go
-import 	"github.com/jcmturner/gokrb5/service"
+import 	"gopkg.in/jcmturner/gokrb5.v1/service"
 if ok, creds, err := serivce.ValidateAPREQ(mt.APReq, kt, r.RemoteAddr); ok {
         // Perform application specifc actions
         // creds object has details about the client identity

+ 0 - 171
crypto/aescts/aescts.go

@@ -1,171 +0,0 @@
-// Package aescts provides AES CipherText Stealing encryption and decryption methods
-package aescts
-
-import (
-	"crypto/aes"
-	"crypto/cipher"
-	"errors"
-	"fmt"
-	"github.com/jcmturner/gokrb5/crypto/common"
-)
-
-// Encrypt the message with the key and the initial vector.
-func Encrypt(key, iv, message []byte) ([]byte, []byte, error) {
-	l := len(message)
-
-	block, err := aes.NewCipher(key)
-	if err != nil {
-		return []byte{}, []byte{}, fmt.Errorf("Error creating cipher: %v", err)
-	}
-	mode := cipher.NewCBCEncrypter(block, iv)
-
-	m := make([]byte, len(message))
-	copy(m, message)
-
-	//Ref: https://tools.ietf.org/html/rfc3962 section 5
-	/*For consistency, ciphertext stealing is always used for the last two
-	blocks of the data to be encrypted, as in [RC5].  If the data length
-	is a multiple of the block size, this is equivalent to plain CBC mode
-	with the last two ciphertext blocks swapped.*/
-	/*The initial vector carried out from one encryption for use in a
-	subsequent encryption is the next-to-last block of the encryption
-	output; this is the encrypted form of the last plaintext block.*/
-	if l <= aes.BlockSize {
-		m, _ = common.ZeroPad(m, aes.BlockSize)
-		mode.CryptBlocks(m, m)
-		return m, m, nil
-	}
-	if l%aes.BlockSize == 0 {
-		mode.CryptBlocks(m, m)
-		iv = m[len(m)-aes.BlockSize:]
-		rb, _ := swapLastTwoBlocks(m, aes.BlockSize)
-		return iv, rb, nil
-	}
-	m, _ = common.ZeroPad(m, aes.BlockSize)
-	rb, pb, lb, err := tailBlocks(m, aes.BlockSize)
-	if err != nil {
-		return []byte{}, []byte{}, fmt.Errorf("Error tailing blocks: %v", err)
-	}
-	var ct []byte
-	if rb != nil {
-		// Encrpt all but the lats 2 blocks and update the rolling iv
-		mode.CryptBlocks(rb, rb)
-		iv = rb[len(rb)-aes.BlockSize:]
-		mode = cipher.NewCBCEncrypter(block, iv)
-		ct = append(ct, rb...)
-	}
-	mode.CryptBlocks(pb, pb)
-	mode = cipher.NewCBCEncrypter(block, pb)
-	mode.CryptBlocks(lb, lb)
-	// Cipher Text Stealing (CTS) - Ref: https://en.wikipedia.org/wiki/Ciphertext_stealing#CBC_ciphertext_stealing
-	// Swap the last two cipher blocks
-	// Truncate the ciphertext to the length of the original plaintext
-	ct = append(ct, lb...)
-	ct = append(ct, pb...)
-	return lb, ct[:l], nil
-}
-
-// Decrypt the ciphertext with the key and the initial vector.
-func Decrypt(key, iv, ciphertext []byte) ([]byte, error) {
-	// Copy the cipher text as golang slices even when passed by value to this method can result in the backing arrays of the calling code value being updated.
-	ct := make([]byte, len(ciphertext))
-	copy(ct, ciphertext)
-	if len(ct) < aes.BlockSize {
-		return []byte{}, fmt.Errorf("Ciphertext is not large enough. It is less that one block size. Blocksize:%v; Ciphertext:%v", aes.BlockSize, len(ct))
-	}
-	// Configure the CBC
-	block, err := aes.NewCipher(key)
-	if err != nil {
-		return nil, fmt.Errorf("Error creating cipher: %v", err)
-	}
-	var mode cipher.BlockMode
-
-	//If ciphertext is multiple of blocksize we just need to swap back the last two blocks and then do CBC
-	//If the ciphertext is just one block we can't swap so we just decrypt
-	if len(ct)%aes.BlockSize == 0 {
-		if len(ct) > aes.BlockSize {
-			ct, _ = swapLastTwoBlocks(ct, aes.BlockSize)
-		}
-		mode = cipher.NewCBCDecrypter(block, iv)
-		message := make([]byte, len(ct))
-		mode.CryptBlocks(message, ct)
-		return message[:len(ct)], nil
-	}
-
-	// Cipher Text Stealing (CTS) using CBC interface. Ref: https://en.wikipedia.org/wiki/Ciphertext_stealing#CBC_ciphertext_stealing
-	// Get ciphertext of the 2nd to last (penultimate) block (cpb), the last block (clb) and the rest (crb)
-	crb, cpb, clb, _ := tailBlocks(ct, aes.BlockSize)
-	v := make([]byte, len(iv), len(iv))
-	copy(v, iv)
-	var message []byte
-	if crb != nil {
-		//If there is more than just the last and the penultimate block we decrypt it and the last bloc of this becomes the iv for later
-		rb := make([]byte, len(crb))
-		mode = cipher.NewCBCDecrypter(block, v)
-		v = crb[len(crb)-aes.BlockSize:]
-		mode.CryptBlocks(rb, crb)
-		message = append(message, rb...)
-	}
-
-	// We need to modify the cipher text
-	// Decryt the 2nd to last (penultimate) block with a the original iv
-	pb := make([]byte, aes.BlockSize)
-	mode = cipher.NewCBCDecrypter(block, iv)
-	mode.CryptBlocks(pb, cpb)
-	// number of byte needed to pad
-	npb := aes.BlockSize - len(ct)%aes.BlockSize
-	//pad last block using the number of bytes needed from the tail of the plaintext 2nd to last (penultimate) block
-	clb = append(clb, pb[len(pb)-npb:]...)
-
-	// Now decrypt the last block in the penultimate position (iv will be from the crb, if the is no crb it's zeros)
-	// iv for the penultimate block decrypted in the last position becomes the modified last block
-	lb := make([]byte, aes.BlockSize)
-	mode = cipher.NewCBCDecrypter(block, v)
-	v = clb
-	mode.CryptBlocks(lb, clb)
-	message = append(message, lb...)
-
-	// Now decrypt the penultimate block in the last position (iv will be from the modified last block)
-	mode = cipher.NewCBCDecrypter(block, v)
-	mode.CryptBlocks(cpb, cpb)
-	message = append(message, cpb...)
-
-	// Truncate to the size of the original cipher text
-	return message[:len(ct)], nil
-}
-
-func tailBlocks(b []byte, c int) ([]byte, []byte, []byte, error) {
-	if len(b) <= c {
-		return []byte{}, []byte{}, []byte{}, errors.New("bytes slice is not larger than one block so cannot tail")
-	}
-	// Get size of last block
-	var lbs int
-	if l := len(b) % aes.BlockSize; l == 0 {
-		lbs = aes.BlockSize
-	} else {
-		lbs = l
-	}
-	// Get last block
-	lb := b[len(b)-lbs:]
-	// Get 2nd to last (penultimate) block
-	pb := b[len(b)-lbs-c : len(b)-lbs]
-	if len(b) > 2*c {
-		rb := b[:len(b)-lbs-c]
-		return rb, pb, lb, nil
-	}
-	return nil, pb, lb, nil
-}
-
-func swapLastTwoBlocks(b []byte, c int) ([]byte, error) {
-	rb, pb, lb, err := tailBlocks(b, c)
-	if err != nil {
-		return nil, err
-	}
-	var out []byte
-	if rb != nil {
-		out = append(out, rb...)
-	}
-	out = append(out, lb...)
-	out = append(out, pb...)
-	return out, nil
-}

+ 0 - 44
crypto/aescts/aescts_test.go

@@ -1,44 +0,0 @@
-package aescts
-
-import (
-	"encoding/hex"
-	"github.com/stretchr/testify/assert"
-	"testing"
-)
-
-func TestAesCts_Encrypt_Decrypt(t *testing.T) {
-	iv := make([]byte, 16)
-	key, _ := hex.DecodeString("636869636b656e207465726979616b69")
-	var tests = []struct {
-		plain  string
-		cipher string
-		nextIV string
-	}{
-		//Test vectors from RFC 3962 Appendix B
-		{"4920776f756c64206c696b652074686520", "c6353568f2bf8cb4d8a580362da7ff7f97", "c6353568f2bf8cb4d8a580362da7ff7f"},
-		{"4920776f756c64206c696b65207468652047656e6572616c20476175277320", "fc00783e0efdb2c1d445d4c8eff7ed2297687268d6ecccc0c07b25e25ecfe5", "fc00783e0efdb2c1d445d4c8eff7ed22"},
-		{"4920776f756c64206c696b65207468652047656e6572616c2047617527732043", "39312523a78662d5be7fcbcc98ebf5a897687268d6ecccc0c07b25e25ecfe584", "39312523a78662d5be7fcbcc98ebf5a8"},
-		{"4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c", "97687268d6ecccc0c07b25e25ecfe584b3fffd940c16a18c1b5549d2f838029e39312523a78662d5be7fcbcc98ebf5", "b3fffd940c16a18c1b5549d2f838029e"},
-		{"4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c20", "97687268d6ecccc0c07b25e25ecfe5849dad8bbb96c4cdc03bc103e1a194bbd839312523a78662d5be7fcbcc98ebf5a8", "9dad8bbb96c4cdc03bc103e1a194bbd8"},
-		{"4920776f756c64206c696b65207468652047656e6572616c20476175277320436869636b656e2c20706c656173652c20616e6420776f6e746f6e20736f75702e", "97687268d6ecccc0c07b25e25ecfe58439312523a78662d5be7fcbcc98ebf5a84807efe836ee89a526730dbc2f7bc8409dad8bbb96c4cdc03bc103e1a194bbd8", "4807efe836ee89a526730dbc2f7bc840"},
-	}
-	for i, test := range tests {
-		m, _ := hex.DecodeString(test.plain)
-		niv, c, err := Encrypt(key, iv, m)
-		if err != nil {
-			t.Errorf("Encryption failed for test %v: %v", i+1, err)
-		}
-		assert.Equal(t, test.cipher, hex.EncodeToString(c), "Encrypted result not as expected")
-		assert.Equal(t, test.nextIV, hex.EncodeToString(niv), "Next state IV not as expected")
-	}
-	//t.Log("AES CTS Encryption tests finished")
-	for i, test := range tests {
-		b, _ := hex.DecodeString(test.cipher)
-		p, err := Decrypt(key, iv, b)
-		if err != nil {
-			t.Errorf("Decryption failed for test %v: %v", i+1, err)
-		}
-		assert.Equal(t, test.plain, hex.EncodeToString(p), "Decrypted result not as expected")
-	}
-	//t.Log("AES CTS Decryption tests finished")
-}

+ 1 - 1
crypto/rfc3962/encryption.go

@@ -5,9 +5,9 @@ import (
 	"crypto/rand"
 	"errors"
 	"fmt"
-	"github.com/jcmturner/gokrb5/crypto/aescts"
 	"github.com/jcmturner/gokrb5/crypto/common"
 	"github.com/jcmturner/gokrb5/crypto/etype"
+	aescts "gopkg.in/jcmturner/aescts.v1"
 )
 
 // EncryptData encrypts the data provided using methods specific to the etype provided as defined in RFC 3962.

+ 1 - 1
crypto/rfc8009/encryption.go

@@ -7,10 +7,10 @@ import (
 	"crypto/rand"
 	"errors"
 	"fmt"
-	"github.com/jcmturner/gokrb5/crypto/aescts"
 	"github.com/jcmturner/gokrb5/crypto/common"
 	"github.com/jcmturner/gokrb5/crypto/etype"
 	"github.com/jcmturner/gokrb5/iana/etypeID"
+	aescts "gopkg.in/jcmturner/aescts.v1"
 )
 
 // EncryptData encrypts the data provided using methods specific to the etype provided as defined in RFC 8009.