...

Source file src/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_test.go

Documentation: github.com/ProtonMail/go-crypto/openpgp/s2k

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package s2k
     6  
     7  import (
     8  	"bytes"
     9  	"crypto"
    10  	"crypto/rand"
    11  	"crypto/sha1"
    12  	_ "crypto/sha256"
    13  	_ "crypto/sha512"
    14  	"encoding/hex"
    15  	"testing"
    16  
    17  	_ "golang.org/x/crypto/ripemd160"
    18  	_ "golang.org/x/crypto/sha3"
    19  )
    20  
    21  var saltedTests = []struct {
    22  	in, out string
    23  }{
    24  	{"hello", "10295ac1"},
    25  	{"world", "ac587a5e"},
    26  	{"foo", "4dda8077"},
    27  	{"bar", "bd8aac6b9ea9cae04eae6a91c6133b58b5d9a61c14f355516ed9370456"},
    28  	{"x", "f1d3f289"},
    29  	{"xxxxxxxxxxxxxxxxxxxxxxx", "e00d7b45"},
    30  }
    31  
    32  func TestSalted(t *testing.T) {
    33  	h := sha1.New()
    34  	salt := [4]byte{1, 2, 3, 4}
    35  
    36  	for i, test := range saltedTests {
    37  		expected, _ := hex.DecodeString(test.out)
    38  		out := make([]byte, len(expected))
    39  		Salted(out, h, []byte(test.in), salt[:])
    40  		if !bytes.Equal(expected, out) {
    41  			t.Errorf("#%d, got: %x want: %x", i, out, expected)
    42  		}
    43  	}
    44  }
    45  
    46  var argon2EncodeTest = []struct {
    47  	in uint32
    48  	out uint8
    49  }{
    50  	{64*1024, 16},
    51  	{64*1024+1, 17},
    52  	{2147483647, 31},
    53  	{2147483649, 31},
    54  	{1, 3},
    55  }
    56  
    57  func TestArgon2EncodeTest(t *testing.T) {
    58  
    59  	for i, tests := range argon2EncodeTest {
    60  		conf  := &Argon2Config {
    61  			Memory: tests.in,
    62  			DegreeOfParallelism: 1,
    63  		}
    64  		out := conf.EncodedMemory()
    65  		if out != tests.out {
    66  			t.Errorf("#%d, got: %x want: %x", i, out, tests.out)
    67  		}
    68  	}
    69  }
    70  
    71  
    72  var iteratedTests = []struct {
    73  	in, out string
    74  }{
    75  	{"hello", "83126105"},
    76  	{"world", "6fa317f9"},
    77  	{"foo", "8fbc35b9"},
    78  	{"bar", "2af5a99b54f093789fd657f19bd245af7604d0f6ae06f66602a46a08ae"},
    79  	{"x", "5a684dfe"},
    80  	{"xxxxxxxxxxxxxxxxxxxxxxx", "18955174"},
    81  }
    82  
    83  func TestIterated(t *testing.T) {
    84  	h := sha1.New()
    85  	salt := [4]byte{4, 3, 2, 1}
    86  
    87  	for i, test := range iteratedTests {
    88  		expected, _ := hex.DecodeString(test.out)
    89  		out := make([]byte, len(expected))
    90  		Iterated(out, h, []byte(test.in), salt[:], 31)
    91  		if !bytes.Equal(expected, out) {
    92  			t.Errorf("#%d, got: %x want: %x", i, out, expected)
    93  		}
    94  	}
    95  }
    96  
    97  var argonTestSalt = "12345678"
    98  var argon2DeriveTests = []struct {
    99  	in, out string
   100  }{
   101  	{"hello", "bf69293d2961bbbebe4c64c745cf44d4"},
   102  	{"world", "dc1bb06234b61c9542d8cf73e2e279d3"},
   103  	{"foo", "7f6baa1c21f0e7eec16cf8fde866775d"},
   104  	{"bar", "2826332c8e62d0cf97cc08f243c5cc9135654bf3a8e46d6a4b4637e42eda2fa0"},
   105  	{"x", "89e5b79435132b98bbcad321532ae7e09f87ac96deca272d6012d367e6350b7d"},
   106  	{"xxxxxxxxxxxxxxxxxxxxxxx", "de0f978013283457e29f0682e0078ad654e7c21bc72886c914c012e56fd5dc91"},
   107  }
   108  
   109  func TestArgon2Derive(t *testing.T) {
   110  	salt := []byte(argonTestSalt)
   111  
   112  	for i, test := range argon2DeriveTests {
   113  		expected, _ := hex.DecodeString(test.out)
   114  		out := make([]byte, len(expected))
   115  		Argon2(out, []byte(test.in), salt[:], 3, 4, 16)
   116  		if !bytes.Equal(expected, out) {
   117  			t.Errorf("#%d, got: %x want: %x", i, out, expected)
   118  		}
   119  	}
   120  }
   121  
   122  var parseTests = []struct {
   123  	spec, in, out string
   124  	dummyKey      bool
   125  	params        Params
   126  }{
   127  	/* Simple with SHA1 */
   128  	{"0002", "hello", "aaf4c61d", false,
   129  		Params{SimpleS2K, 0x02, [16]byte{}, 0, 0, 0, 0}},
   130  	/* Salted with SHA1 */
   131  	{"01020102030405060708", "hello", "f4f7d67e", false,
   132  		Params{SaltedS2K, 0x02, [16]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0, 0, 0, 0}},
   133  	/* Iterated with SHA1 */
   134  	{"03020102030405060708f1", "hello", "f2a57b7c", false,
   135  		Params{IteratedSaltedS2K, 0x02, [16]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0xf1, 0, 0, 0}},
   136  	/* Argon2 */
   137  	{"0401020304050607080102030405060708030410", "hello", "dabc018a", false,
   138  		Params{Argon2S2K, 0x00, [16]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}, 0, 0x03, 0x04, 0x10}},
   139  	/* GNU dummy S2K */
   140  	{"6502474e5501", "", "", true,
   141  		Params{GnuS2K, 0x02, [16]byte{}, 0, 0, 0, 0}},
   142  }
   143  
   144  func TestParseIntoParams(t *testing.T) {
   145  	for i, test := range parseTests {
   146  		spec, _ := hex.DecodeString(test.spec)
   147  		buf := bytes.NewBuffer(spec)
   148  		params, err := ParseIntoParams(buf)
   149  		if err != nil {
   150  			t.Errorf("%d: ParseIntoParams returned error: %s", i, err)
   151  			continue
   152  		}
   153  
   154  		if test.params.mode != params.mode || test.params.hashId != params.hashId || test.params.countByte != params.countByte ||
   155  			!bytes.Equal(test.params.salt(), params.salt()) {
   156  			t.Errorf("%d: Wrong config, got: %+v want: %+v", i, params, test.params)
   157  		}
   158  
   159  		if params.Dummy() != test.dummyKey {
   160  			t.Errorf("%d: Got GNU dummy %v, expected %v", i, params.Dummy(), test.dummyKey)
   161  		}
   162  
   163  		if !test.dummyKey {
   164  			expectedHash, _ := hex.DecodeString(test.out)
   165  			out := make([]byte, len(expectedHash))
   166  
   167  			f, err := params.Function()
   168  			if err != nil {
   169  				t.Errorf("%d: params.Function() returned error: %s", i, err)
   170  				continue
   171  			}
   172  			f(out, []byte(test.in))
   173  			if !bytes.Equal(out, expectedHash) {
   174  				t.Errorf("%d: Wrong output got: %x want: %x", i, out, expectedHash)
   175  			}
   176  		}
   177  
   178  		var reserialized bytes.Buffer
   179  		err = params.Serialize(&reserialized)
   180  		if err != nil {
   181  			t.Errorf("%d: params.Serialize() returned error: %s", i, err)
   182  			continue
   183  		}
   184  		if !bytes.Equal(reserialized.Bytes(), spec) {
   185  			t.Errorf("%d: Wrong reserialized got: %x want: %x", i, reserialized.Bytes(), spec)
   186  		}
   187  		if testing.Short() {
   188  			break
   189  		}
   190  	}
   191  }
   192  
   193  func TestSerializeSaltedOK(t *testing.T) {
   194  	hashes := []crypto.Hash{crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224, crypto.SHA3_256,
   195  		crypto.SHA3_512}
   196  	for _, h := range hashes {
   197  		params := testSerializeConfigOK(t, &Config{S2KMode: SaltedS2K, Hash: h, PassphraseIsHighEntropy: true})
   198  
   199  		if params.mode != SaltedS2K {
   200  			t.Fatalf("Wrong mode, expected %d got %d", SaltedS2K, params.mode)
   201  		}
   202  	}
   203  }
   204  
   205  func TestSerializeSaltedLowEntropy(t *testing.T) {
   206  	hashes := []crypto.Hash{crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224, crypto.SHA3_256,
   207  		crypto.SHA3_512}
   208  	for _, h := range hashes {
   209  		params := testSerializeConfigOK(t, &Config{S2KMode: SaltedS2K, Hash: h})
   210  
   211  		if params.mode != IteratedSaltedS2K {
   212  			t.Fatalf("Wrong mode, expected %d got %d", IteratedSaltedS2K, params.mode)
   213  		}
   214  
   215  		if params.countByte != 224 { // The default case. Corresponding to 16777216
   216  			t.Fatalf("Wrong count byte, expected %d got %d", 224, params.countByte)
   217  		}
   218  	}
   219  }
   220  
   221  func TestSerializeSaltedIteratedOK(t *testing.T) {
   222  	hashes := []crypto.Hash{crypto.SHA256, crypto.SHA384, crypto.SHA512, crypto.SHA224, crypto.SHA3_256,
   223  		crypto.SHA3_512}
   224  	// {input, expected}
   225  	testCounts := [][]int{{-1, 96}, {0, 224}, {1024, 96}, {65536, 96}, {4063232, 191}, {65011712, 255}}
   226  	for _, h := range hashes {
   227  		for _, c := range testCounts {
   228  			params := testSerializeConfigOK(t, &Config{Hash: h, S2KCount: c[0]})
   229  
   230  			if params.mode != IteratedSaltedS2K {
   231  				t.Fatalf("Wrong mode, expected %d got %d", IteratedSaltedS2K, params.mode)
   232  			}
   233  
   234  			if int(params.countByte) != c[1] {
   235  				t.Fatalf("Wrong count byte, expected %d got %d", c[1], params.countByte)
   236  			}
   237  		}
   238  	}
   239  }
   240  
   241  func TestSerializeOKArgon(t *testing.T) {
   242  	config := &Config{
   243  		S2KMode: Argon2S2K,
   244  		Argon2Config: &Argon2Config{NumberOfPasses: 3, DegreeOfParallelism: 4, Memory: 64*1024},
   245  	}
   246  
   247  	params := testSerializeConfigOK(t, config)
   248  
   249  	if params.mode != Argon2S2K {
   250  		t.Fatalf("Wrong mode, expected %d got %d", Argon2S2K, params.mode)
   251  	}
   252  }
   253  
   254  func testSerializeConfigOK(t *testing.T, c *Config) *Params {
   255  	buf := bytes.NewBuffer(nil)
   256  	key := make([]byte, 16)
   257  	passphrase := []byte("testing")
   258  	err := Serialize(buf, key, rand.Reader, passphrase, c)
   259  	if err != nil {
   260  		t.Fatalf("failed to serialize with config %+v: %s", c, err)
   261  	}
   262  
   263  	f, err := Parse(bytes.NewBuffer(buf.Bytes()))
   264  	if err != nil {
   265  		t.Fatalf("failed to reparse: %s", err)
   266  	}
   267  	key2 := make([]byte, len(key))
   268  	f(key2, passphrase)
   269  	if !bytes.Equal(key2, key) {
   270  		t.Errorf("keys don't match: %x (serialied) vs %x (parsed)", key, key2)
   271  	}
   272  
   273  	params, err := ParseIntoParams(bytes.NewBuffer(buf.Bytes()))
   274  	if err != nil {
   275  		t.Fatalf("failed to parse params: %s", err)
   276  	}
   277  
   278  	return params
   279  }
   280  

View as plain text