github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/accesscontrol/crypto/utils/aes_test.go (about)

     1  /*
     2  Copyright IBM Corp. 2016 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // This package contains unit-tests for the
    18  // github.com/hyperledger/fabric/core/crypto/primitives package
    19  package utils
    20  
    21  import (
    22  	"bytes"
    23  	"crypto/aes"
    24  	"crypto/rand"
    25  	"math/big"
    26  	"testing"
    27  
    28  	"github.com/hyperledger/fabric/core/crypto/primitives"
    29  )
    30  
    31  // TestCBCPKCS7EncryptCBCPKCS7Decrypt encrypts using CBCPKCS7Encrypt and decrypts using CBCPKCS7Decrypt.
    32  func TestCBCPKCS7EncryptCBCPKCS7Decrypt(t *testing.T) {
    33  
    34  	// Note: The purpose of this test is not to test AES-256 in CBC mode's strength
    35  	// ... but rather to verify the code wrapping/unwrapping the cipher.
    36  	key := make([]byte, AESKeyLength)
    37  	rand.Reader.Read(key)
    38  
    39  	//                  123456789012345678901234567890123456789012
    40  	var ptext = []byte("a message with arbitrary length (42 bytes)")
    41  
    42  	encrypted, encErr := CBCPKCS7Encrypt(key, ptext)
    43  	if encErr != nil {
    44  		t.Fatalf("Error encrypting '%s': %s", ptext, encErr)
    45  	}
    46  
    47  	decrypted, dErr := CBCPKCS7Decrypt(key, encrypted)
    48  	if dErr != nil {
    49  		t.Fatalf("Error decrypting the encrypted '%s': %v", ptext, dErr)
    50  	}
    51  
    52  	if string(ptext[:]) != string(decrypted[:]) {
    53  		t.Fatal("Decrypt( Encrypt( ptext ) ) != ptext: Ciphertext decryption with the same key must result in the original plaintext!")
    54  	}
    55  
    56  }
    57  
    58  // TestPKCS7Padding verifies the PKCS#7 padding, using a human readable plaintext.
    59  func TestPKCS7Padding(t *testing.T) {
    60  
    61  	// 0 byte/length ptext
    62  	ptext := []byte("")
    63  	expected := []byte{16, 16, 16, 16,
    64  		16, 16, 16, 16,
    65  		16, 16, 16, 16,
    66  		16, 16, 16, 16}
    67  	result := PKCS7Padding(ptext)
    68  
    69  	if !bytes.Equal(expected, result) {
    70  		t.Fatal("Padding error! Expected: ", expected, "', received: '", result, "'")
    71  	}
    72  
    73  	// 1 byte/length ptext
    74  	ptext = []byte("1")
    75  	expected = []byte{'1', 15, 15, 15,
    76  		15, 15, 15, 15,
    77  		15, 15, 15, 15,
    78  		15, 15, 15, 15}
    79  	result = PKCS7Padding(ptext)
    80  
    81  	if !bytes.Equal(expected, result) {
    82  		t.Fatal("Padding error! Expected: '", expected, "', received: '", result, "'")
    83  	}
    84  
    85  	// 2 byte/length ptext
    86  	ptext = []byte("12")
    87  	expected = []byte{'1', '2', 14, 14,
    88  		14, 14, 14, 14,
    89  		14, 14, 14, 14,
    90  		14, 14, 14, 14}
    91  	result = PKCS7Padding(ptext)
    92  
    93  	if !bytes.Equal(expected, result) {
    94  		t.Fatal("Padding error! Expected: '", expected, "', received: '", result, "'")
    95  	}
    96  
    97  	// 3 to aes.BlockSize-1 byte plaintext
    98  	ptext = []byte("1234567890ABCDEF")
    99  	for i := 3; i < aes.BlockSize; i++ {
   100  		result := PKCS7Padding(ptext[:i])
   101  
   102  		padding := aes.BlockSize - i
   103  		expectedPadding := bytes.Repeat([]byte{byte(padding)}, padding)
   104  		expected = append(ptext[:i], expectedPadding...)
   105  
   106  		if !bytes.Equal(result, expected) {
   107  			t.Fatal("Padding error! Expected: '", expected, "', received: '", result, "'")
   108  		}
   109  
   110  	}
   111  
   112  	// aes.BlockSize length ptext
   113  	ptext = bytes.Repeat([]byte{byte('x')}, aes.BlockSize)
   114  	result = PKCS7Padding(ptext)
   115  
   116  	expectedPadding := bytes.Repeat([]byte{byte(aes.BlockSize)}, aes.BlockSize)
   117  	expected = append(ptext, expectedPadding...)
   118  
   119  	if len(result) != 2*aes.BlockSize {
   120  		t.Fatal("Padding error: expected the length of the returned slice to be 2 times aes.BlockSize")
   121  	}
   122  
   123  	if !bytes.Equal(expected, result) {
   124  		t.Fatal("Padding error! Expected: '", expected, "', received: '", result, "'")
   125  	}
   126  
   127  }
   128  
   129  // TestPKCS7UnPadding verifies the PKCS#7 unpadding, using a human readable plaintext.
   130  func TestPKCS7UnPadding(t *testing.T) {
   131  
   132  	// 0 byte/length ptext
   133  	expected := []byte("")
   134  	ptext := []byte{16, 16, 16, 16,
   135  		16, 16, 16, 16,
   136  		16, 16, 16, 16,
   137  		16, 16, 16, 16}
   138  
   139  	result, _ := PKCS7UnPadding(ptext)
   140  
   141  	if !bytes.Equal(expected, result) {
   142  		t.Fatal("UnPadding error! Expected: '", expected, "', received: '", result, "'")
   143  	}
   144  
   145  	// 1 byte/length ptext
   146  	expected = []byte("1")
   147  	ptext = []byte{'1', 15, 15, 15,
   148  		15, 15, 15, 15,
   149  		15, 15, 15, 15,
   150  		15, 15, 15, 15}
   151  
   152  	result, _ = PKCS7UnPadding(ptext)
   153  
   154  	if !bytes.Equal(expected, result) {
   155  		t.Fatal("UnPadding error! Expected: '", expected, "', received: '", result, "'")
   156  	}
   157  
   158  	// 2 byte/length ptext
   159  	expected = []byte("12")
   160  	ptext = []byte{'1', '2', 14, 14,
   161  		14, 14, 14, 14,
   162  		14, 14, 14, 14,
   163  		14, 14, 14, 14}
   164  
   165  	result, _ = PKCS7UnPadding(ptext)
   166  
   167  	if !bytes.Equal(expected, result) {
   168  		t.Fatal("UnPadding error! Expected: '", expected, "', received: '", result, "'")
   169  	}
   170  
   171  	// 3 to aes.BlockSize-1 byte plaintext
   172  	base := []byte("1234567890ABCDEF")
   173  	for i := 3; i < aes.BlockSize; i++ {
   174  		iPad := aes.BlockSize - i
   175  		padding := bytes.Repeat([]byte{byte(iPad)}, iPad)
   176  		ptext = append(base[:i], padding...)
   177  
   178  		expected := base[:i]
   179  		result, _ := PKCS7UnPadding(ptext)
   180  
   181  		if !bytes.Equal(result, expected) {
   182  			t.Fatal("UnPadding error! Expected: '", expected, "', received: '", result, "'")
   183  		}
   184  
   185  	}
   186  
   187  	// aes.BlockSize length ptext
   188  	expected = bytes.Repeat([]byte{byte('x')}, aes.BlockSize)
   189  	padding := bytes.Repeat([]byte{byte(aes.BlockSize)}, aes.BlockSize)
   190  	ptext = append(expected, padding...)
   191  
   192  	result, _ = PKCS7UnPadding(ptext)
   193  
   194  	if !bytes.Equal(expected, result) {
   195  		t.Fatal("UnPadding error! Expected: '", expected, "', received: '", result, "'")
   196  	}
   197  }
   198  
   199  // TestCBCEncryptCBCPKCS7Decrypt_BlockSizeLengthPlaintext verifies that CBCPKCS7Decrypt returns an error
   200  // when attempting to decrypt ciphertext of an irreproducible length.
   201  func TestCBCEncryptCBCPKCS7Decrypt_BlockSizeLengthPlaintext(t *testing.T) {
   202  
   203  	// One of the purposes of this test is to also document and clarify the expected behavior, i.e., that an extra
   204  	// block is appended to the message at the padding stage, as per the spec of PKCS#7 v1.5 [see RFC-2315 p.21]
   205  	key := make([]byte, AESKeyLength)
   206  	rand.Reader.Read(key)
   207  
   208  	//                  1234567890123456
   209  	var ptext = []byte("a 16 byte messag")
   210  
   211  	encrypted, encErr := CBCEncrypt(key, ptext)
   212  	if encErr != nil {
   213  		t.Fatalf("Error encrypting '%s': %v", ptext, encErr)
   214  	}
   215  
   216  	decrypted, dErr := CBCPKCS7Decrypt(key, encrypted)
   217  	if dErr == nil {
   218  		t.Fatalf("Expected an error decrypting ptext '%s'. Decrypted to '%v'", dErr, decrypted)
   219  	}
   220  }
   221  
   222  // TestCBCPKCS7EncryptCBCDecrypt_ExpectingCorruptMessage verifies that CBCDecrypt can decrypt the unpadded
   223  // version of the ciphertext, of a message of BlockSize length.
   224  func TestCBCPKCS7EncryptCBCDecrypt_ExpectingCorruptMessage(t *testing.T) {
   225  
   226  	// One of the purposes of this test is to also document and clarify the expected behavior, i.e., that an extra
   227  	// block is appended to the message at the padding stage, as per the spec of PKCS#7 v1.5 [see RFC-2315 p.21]
   228  	key := make([]byte, AESKeyLength)
   229  	rand.Reader.Read(key)
   230  
   231  	//                  0123456789ABCDEF
   232  	var ptext = []byte("a 16 byte messag")
   233  
   234  	encrypted, encErr := CBCPKCS7Encrypt(key, ptext)
   235  	if encErr != nil {
   236  		t.Fatalf("Error encrypting ptext %v", encErr)
   237  	}
   238  
   239  	decrypted, dErr := CBCDecrypt(key, encrypted)
   240  	if dErr != nil {
   241  		t.Fatalf("Error encrypting ptext %v, %v", dErr, decrypted)
   242  	}
   243  
   244  	if string(ptext[:]) != string(decrypted[:aes.BlockSize]) {
   245  		t.Log("ptext: ", ptext)
   246  		t.Log("decrypted: ", decrypted[:aes.BlockSize])
   247  		t.Fatal("Encryption->Decryption with same key should result in original ptext")
   248  	}
   249  
   250  	if !bytes.Equal(decrypted[aes.BlockSize:], bytes.Repeat([]byte{byte(aes.BlockSize)}, aes.BlockSize)) {
   251  		t.Fatal("Expected extra block with padding in encrypted ptext", decrypted)
   252  	}
   253  
   254  }
   255  
   256  // TestCBCPKCS7Encrypt_EmptyPlaintext encrypts and pad an empty ptext. Verifying as well that the ciphertext length is as expected.
   257  func TestCBCPKCS7Encrypt_EmptyPlaintext(t *testing.T) {
   258  
   259  	key := make([]byte, AESKeyLength)
   260  	rand.Reader.Read(key)
   261  
   262  	t.Log("Generated key: ", key)
   263  
   264  	var emptyPlaintext = []byte("")
   265  	t.Log("Plaintext length: ", len(emptyPlaintext))
   266  
   267  	ciphertext, encErr := CBCPKCS7Encrypt(key, emptyPlaintext)
   268  	if encErr != nil {
   269  		t.Fatalf("Error encrypting '%v'", encErr)
   270  	}
   271  
   272  	// Expected ciphertext length: AESKeyLength (=32)
   273  	// As part of the padding, at least one block gets encrypted (while the first block is the IV)
   274  	const expectedLength = aes.BlockSize + aes.BlockSize
   275  	if len(ciphertext) != expectedLength {
   276  		t.Fatalf("Wrong ciphertext length. Expected %d, recieved %d", expectedLength, len(ciphertext))
   277  	}
   278  
   279  	t.Log("Ciphertext length: ", len(ciphertext))
   280  	t.Log("Cipher: ", ciphertext)
   281  }
   282  
   283  // TestCBCEncrypt_EmptyPlaintext encrypts an empty message. Verifying as well that the ciphertext length is as expected.
   284  func TestCBCEncrypt_EmptyPlaintext(t *testing.T) {
   285  
   286  	key := make([]byte, AESKeyLength)
   287  	rand.Reader.Read(key)
   288  	t.Log("Generated key: ", key)
   289  
   290  	var emptyPlaintext = []byte("")
   291  	t.Log("Message length: ", len(emptyPlaintext))
   292  
   293  	ciphertext, encErr := CBCEncrypt(key, emptyPlaintext)
   294  	if encErr != nil {
   295  	}
   296  
   297  	t.Log("Ciphertext length: ", len(ciphertext))
   298  
   299  	// Expected cipher length: aes.BlockSize, the first and only block is the IV
   300  	var expectedLength = aes.BlockSize
   301  
   302  	if len(ciphertext) != expectedLength {
   303  		t.Fatalf("Wrong ciphertext length. Expected: '%d', received: '%d'", expectedLength, len(ciphertext))
   304  	}
   305  	t.Log("Ciphertext: ", ciphertext)
   306  }
   307  
   308  // TestCBCPKCS7Encrypt_VerifyRandomIVs encrypts twice with same key. The first 16 bytes should be different if IV is generated randomly.
   309  func TestCBCPKCS7Encrypt_VerifyRandomIVs(t *testing.T) {
   310  
   311  	key := make([]byte, aes.BlockSize)
   312  	rand.Reader.Read(key)
   313  	t.Log("Key 1", key)
   314  
   315  	var ptext = []byte("a message to encrypt")
   316  
   317  	ciphertext1, err := CBCPKCS7Encrypt(key, ptext)
   318  	if err != nil {
   319  		t.Fatalf("Error encrypting '%s': %s", ptext, err)
   320  	}
   321  
   322  	// Expecting a different IV if same message is encrypted with same key
   323  	ciphertext2, err := CBCPKCS7Encrypt(key, ptext)
   324  	if err != nil {
   325  		t.Fatalf("Error encrypting '%s': %s", ptext, err)
   326  	}
   327  
   328  	iv1 := ciphertext1[:aes.BlockSize]
   329  	iv2 := ciphertext2[:aes.BlockSize]
   330  
   331  	t.Log("Ciphertext1: ", iv1)
   332  	t.Log("Ciphertext2: ", iv2)
   333  	t.Log("bytes.Equal: ", bytes.Equal(iv1, iv2))
   334  
   335  	if bytes.Equal(iv1, iv2) {
   336  		t.Fatal("Error: ciphertexts contain identical initialization vectors (IVs)")
   337  	}
   338  }
   339  
   340  // TestCBCPKCS7Encrypt_CorrectCiphertextLengthCheck verifies that the returned ciphertext lengths are as expected.
   341  func TestCBCPKCS7Encrypt_CorrectCiphertextLengthCheck(t *testing.T) {
   342  
   343  	key := make([]byte, aes.BlockSize)
   344  	rand.Reader.Read(key)
   345  
   346  	// length of message (in bytes) == aes.BlockSize (16 bytes)
   347  	// The expected cipher length = IV length (1 block) + 1 block message
   348  
   349  	var ptext = []byte("0123456789ABCDEF")
   350  
   351  	for i := 1; i < aes.BlockSize; i++ {
   352  		ciphertext, err := CBCPKCS7Encrypt(key, ptext[:i])
   353  		if err != nil {
   354  			t.Fatal("Error encrypting '", ptext, "'")
   355  		}
   356  
   357  		expectedLength := aes.BlockSize + aes.BlockSize
   358  		if len(ciphertext) != expectedLength {
   359  			t.Fatalf("Incorrect ciphertext incorrect: expected '%d', received '%d'", expectedLength, len(ciphertext))
   360  		}
   361  	}
   362  }
   363  
   364  // TestCBCEncryptCBCDecrypt_KeyMismatch attempts to decrypt with a different key than the one used for encryption.
   365  func TestCBCEncryptCBCDecrypt_KeyMismatch(t *testing.T) {
   366  
   367  	// Generate a random key
   368  	key := make([]byte, aes.BlockSize)
   369  	rand.Reader.Read(key)
   370  
   371  	// Clone & tamper with the key
   372  	wrongKey := make([]byte, aes.BlockSize)
   373  	copy(wrongKey, key[:])
   374  	wrongKey[0] = key[0] + 1
   375  
   376  	var ptext = []byte("1234567890ABCDEF")
   377  	encrypted, encErr := CBCEncrypt(key, ptext)
   378  	if encErr != nil {
   379  		t.Fatalf("Error encrypting '%s': %v", ptext, encErr)
   380  	}
   381  
   382  	decrypted, decErr := CBCDecrypt(wrongKey, encrypted)
   383  	if decErr != nil {
   384  		t.Fatalf("Error decrypting '%s': %v", ptext, decErr)
   385  	}
   386  
   387  	if string(ptext[:]) == string(decrypted[:]) {
   388  		t.Fatal("Decrypting a ciphertext with a different key than the one used for encrypting it - should not result in the original plaintext.")
   389  	}
   390  }
   391  
   392  // TestCBCEncryptCBCDecrypt encrypts with CBCEncrypt and decrypt with CBCDecrypt.
   393  func TestCBCEncryptCBCDecrypt(t *testing.T) {
   394  
   395  	key := make([]byte, AESKeyLength)
   396  	rand.Reader.Read(key)
   397  
   398  	//                  1234567890123456
   399  	var ptext = []byte("a 16 byte messag")
   400  
   401  	encrypted, encErr := CBCEncrypt(key, ptext)
   402  	if encErr != nil {
   403  		t.Fatalf("Error encrypting '%s': %v", ptext, encErr)
   404  	}
   405  
   406  	decrypted, decErr := CBCDecrypt(key, encrypted)
   407  	if decErr != nil {
   408  		t.Fatalf("Error decrypting '%s': %v", ptext, decErr)
   409  	}
   410  
   411  	if string(ptext[:]) != string(decrypted[:]) {
   412  		t.Fatal("Encryption->Decryption with same key should result in the original plaintext.")
   413  	}
   414  }
   415  
   416  // TestAESRelatedUtilFunctions tests various functions commonly used in fabric wrt AES
   417  func TestAESRelatedUtilFunctions(t *testing.T) {
   418  
   419  	key, err := GenAESKey()
   420  	if err != nil {
   421  		t.Fatalf("Failed generating AES key [%s]", err)
   422  	}
   423  
   424  	for i := 1; i < 100; i++ {
   425  		len, err := rand.Int(rand.Reader, big.NewInt(1024))
   426  		if err != nil {
   427  			t.Fatalf("Failed generating AES key [%s]", err)
   428  		}
   429  		msg, err := primitives.GetRandomBytes(int(len.Int64()) + 1)
   430  		if err != nil {
   431  			t.Fatalf("Failed generating AES key [%s]", err)
   432  		}
   433  
   434  		ct, err := CBCPKCS7Encrypt(key, msg)
   435  		if err != nil {
   436  			t.Fatalf("Failed encrypting [%s]", err)
   437  		}
   438  
   439  		msg2, err := CBCPKCS7Decrypt(key, ct)
   440  		if err != nil {
   441  			t.Fatalf("Failed decrypting [%s]", err)
   442  		}
   443  
   444  		if 0 != bytes.Compare(msg, msg2) {
   445  			t.Fatalf("Wrong decryption output [%x][%x]", msg, msg2)
   446  		}
   447  
   448  	}
   449  
   450  }
   451  
   452  // TestVariousAESKeyEncoding tests some AES <-> PEM conversions
   453  func TestVariousAESKeyEncoding(t *testing.T) {
   454  	key, err := GenAESKey()
   455  	if err != nil {
   456  		t.Fatalf("Failed generating AES key [%s]", err)
   457  	}
   458  
   459  	// PEM format
   460  	pem := AEStoPEM(key)
   461  	keyFromPEM, err := PEMtoAES(pem, nil)
   462  	if err != nil {
   463  		t.Fatalf("Failed converting PEM to AES key [%s]", err)
   464  	}
   465  	if 0 != bytes.Compare(key, keyFromPEM) {
   466  		t.Fatalf("Failed converting PEM to AES key. Keys are different [%x][%x]", key, keyFromPEM)
   467  	}
   468  
   469  	// Encrypted PEM format
   470  	pem, err = AEStoEncryptedPEM(key, []byte("passwd"))
   471  	if err != nil {
   472  		t.Fatalf("Failed converting AES key to Encrypted PEM [%s]", err)
   473  	}
   474  	keyFromPEM, err = PEMtoAES(pem, []byte("passwd"))
   475  	if err != nil {
   476  		t.Fatalf("Failed converting encrypted PEM to AES key [%s]", err)
   477  	}
   478  	if 0 != bytes.Compare(key, keyFromPEM) {
   479  		t.Fatalf("Failed converting encrypted PEM to AES key. Keys are different [%x][%x]", key, keyFromPEM)
   480  	}
   481  }