github.com/letsencrypt/trillian@v1.1.2-0.20180615153820-ae375a99d36a/crypto/keys/pem/pem_test.go (about)

     1  // Copyright 2016 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package pem_test
    16  
    17  import (
    18  	"crypto"
    19  	"testing"
    20  
    21  	. "github.com/google/trillian/crypto/keys/pem"
    22  	ktestonly "github.com/google/trillian/crypto/keys/testonly"
    23  	"github.com/google/trillian/crypto/keyspb"
    24  	"github.com/google/trillian/testonly"
    25  )
    26  
    27  const (
    28  	_ = `
    29  -----BEGIN PUBLIC KEY-----
    30  MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEvuynpVdR+5xSNaVBb//1fqO6Nb/nC+WvRQ4bALzy4G+QbByvO1Qpm2eUzTdDUnsLN5hp3pIXYAmtjvjY1fFZEg==
    31  -----END PUBLIC KEY-----`
    32  	ecdsaPrivateKey = `
    33  -----BEGIN PRIVATE KEY-----
    34  MHcCAQEEIHG5m/q2sUSa4P8pRZgYt3K0ESFSKp1qp15VjJhpLle4oAoGCCqGSM49AwEHoUQDQgAEvuynpVdR+5xSNaVBb//1fqO6Nb/nC+WvRQ4bALzy4G+QbByvO1Qpm2eUzTdDUnsLN5hp3pIXYAmtjvjY1fFZEg==
    35  -----END PRIVATE KEY-----
    36  `
    37  	_ = `
    38  -----BEGIN PUBLIC KEY-----
    39  MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsMB4reLZhs+2ReYX01nZpqLBQ9uhcZvBmzH54RsZDTb5khw+luSXKbLKXxdbQfrsxURbeVdugDNnV897VI43znuiKJ19Y/XS3N5Z7Q97/GOxOxGFObP0DovCAPblxAMaQBb+U9jkVt/4bHcNIOTZl/lXgX+yp58lH5uPfDwav/hVNg7QkAW3BxQZ5wiLTTZUILoTMjax4R24pULlg/Wt/rT4bDj8rxUgYR60MuO93jdBtNGwmzdCYyk4cEmrPEgCueRC6jFafUzlLjvuX89ES9n98LxX+gBANA7RpVPkJd0kfWFHO1JRUEJr++WjU3x4la2Xs4tUNX4QBSJP4XEOXwIDAQAB
    40  -----END PUBLIC KEY-----`
    41  	rsaPrivateKey = `
    42  -----BEGIN PRIVATE KEY-----
    43  MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCwwHit4tmGz7ZF5hfTWdmmosFD26Fxm8GbMfnhGxkNNvmSHD6W5JcpsspfF1tB+uzFRFt5V26AM2dXz3tUjjfOe6IonX1j9dLc3lntD3v8Y7E7EYU5s/QOi8IA9uXEAxpAFv5T2ORW3/hsdw0g5NmX+VeBf7KnnyUfm498PBq/+FU2DtCQBbcHFBnnCItNNlQguhMyNrHhHbilQuWD9a3+tPhsOPyvFSBhHrQy473eN0G00bCbN0JjKThwSas8SAK55ELqMVp9TOUuO+5fz0RL2f3wvFf6AEA0DtGlU+Ql3SR9YUc7UlFQQmv75aNTfHiVrZezi1Q1fhAFIk/hcQ5fAgMBAAECggEAcpuq5J2GjQqcVwCWjF3jalB4XsbIDUGArWAfdd47RT1TYHFeCDua5Nfgrv4XF1ZcNqFXavvNU+WA6ghIIRDCkOnLwOg1yR45pyuqRbPXolUGM5Xtu/e6lb/7gOKXI50bZVlDehzWGprJm5MqeRzLFub/3aFut4/S44bb6COU+Mo6bsm+/2hcuOtUeDR5fOc49tTAZZSG6kVAXdWG5raU4a/Qx6LCR5zMjhzqy8FMGkW+eww243WM/5RCW6pzgwjFVPyfrg/Jqc2IgAPuFEStvK6jAsPaZxb7t1ue79ku8+xLDpJSgLUF3jU9Qy8+VphnmbHrYSqDSNUyfj8+qcbI0QKBgQDc/GD7Yprw4zp3IqLoYd96dqJtlloUgd7kGebDfAftAgo2ooS8tpbAYGvgmeMDqAfqfTkOJUACCHptnpUWusXJqW6SW9bk17jGb/pPcQiXmaNPGYbpPlamueUmS9gdatvw6iXewRqjltNMng+mfbvAmaFe+qeqCq86R9BoUFVBCQKBgQDMwd+6DKGKH/hgChweUtNLMmeOmzYskcUL43cLeAAwwlL4DruLthBb/0SYeMQ+sXpYDL3b1/i03Ln5P5g8KFL8EgIayInlZJHiHjOn9LF+S5gv5snI0Fdk2O8eNHCSiS0+qqPU8ZKTKwnbt8M+OqLhJD0C7N35oYAoCj0uhSp2JwKBgQDBIxqn2tBMBGyOvwjeTNwCrjjbynJERhVGCpUy+O38aLIAeh3EyVgMHrlp/VT5VxxEBtmc0VWV8U7/C4CF8wr2a0ymQfoY26k0VZ3RXJsD1FV0xnyw0bjt0r7Br7vcSg6cCii6/M6Jd0KJTgOjoXQ8qojs9+kdpmTrbORqpvs78QKBgQC13ZW8CLAKoS7ZDuG+xU5LQi/c6FuL5sWgM59vHlz88f0DuwI1q7aIIAlrbAjSroy+XELeW8vZyRueGTA8boyWu+AGrgxdJaC1uKGlEp/8T2STV2fu565YMp7gsy8x2InJWYM/BnpsIRQWhffy893sH2XZjU30BdBwv/drtHfsjQKBgHQgInEA+pwo/laVgVkuIlL/0avlRRG06TsMUJYDP9jOfzdoWZrsCVr4uLXMR1zJ2I/tmKv+u+35luu2rVnItB7hSJgMy+6Bxj4DL5QE9BuLVARDMGrj05oZXPw9954HjN87b4dVvSKl2hPz6lcsKDlPJy+OvXdsZxfc9NaCCQNT
    44  -----END PRIVATE KEY-----
    45  `
    46  	_ = `
    47  -----BEGIN PUBLIC KEY-----
    48  MIIDRjCCAjkGByqGSM44BAEwggIsAoIBAQDgLI6pXvqpcOY33lzeZrjUBHxphiz0I9VKF9vGpWymNfBptQ75bpQFe16jBjaOGwDImASHTp53XskQJLOXC4bZxoRUHsm8bHQVZHQhYgxn8ZDQX/40zOR1d73y1TXSiULo6rDKVlM+fFcm33tGv+ZOdfaIhW17c5jvDAy6UWqQakasvL+kfiejIDGHjLVFWwX0vLCG+pAomgO6snQHGcPhDO9uxEYPd9on7YTgBrpa2IcXk5jFeY8xOxMnMwoBojRvH97+ivdBR1yW8f+4FAGg5o1eFV5ZqoUAF8GO3BBEwluMGNeT7gMgl4PO8N8xBxJulHd3tLW5qkW0cBPwkbzzAiEAvdYeMPamsFAyd7s07dt78wxXyHGrwVl2AcQBo0QTATkCggEASH9Rp+EjNkL7uCqGJ78P4tjJM+2+xaEhZpJ/kTzq6DtdFhu5Rov6lN5NnZKPSUNYr9Vkmu88ru0iND1N37z0rJpImksXKxCv0AwBkwtqCwf9jjkTrZiGRzP8xf789wK+uG7Uud20ml9QzXKr9Af9WrRx3DtCq44PBaIlhPvpZS9znCZsuUZqYZFW3/oD4EhwPgVLSWeulh1t33ku3mYQwVS8ZTdJGPyFRoD1dcQ4EchR4ce0u0nTXlqErWhfnmb9msF6dFCV0Mx5yrqxkEHbJ/vZgB4zAdOke7XiJsWqIok/7IJpJuVOvkY9NHgBdlq3xU180+pEo2NrGm4pbrGm1wOCAQUAAoIBAAGbucHEfgtcu++OQQjYqneukv4zqcP/PCJTP+GuXen6SH25V2ZlHC88lG6qdZVBPWZidAb9BSoUQpW7BzauKRqH7rKOsIeqvEPCiWBKA781Zi5HAWGhC4INJJx54Q66F54DkGlTRVFkXlGpAIudhfAIG//MyO9TIsLSgRyqjKWVm+/XhWDIT5iMJZZ/IgmbICueaa7go8poHuTTyUDPHPIeL5d9Aru7qD4JtX+UVy6GYKhWx/guv+A7zyJ8d1kMLsmUAro80DLPDoais2I8YPpbu+xTSLLswIYddDdwg3P8mMAGzuWY/ZLumwpRr/fbI+t2Sm9KKGNGkGGIKAg43cs=
    49  -----END PUBLIC KEY-----`
    50  	corruptEcdsaPrivateKey = `
    51  -----BEGIN PRIVATE KEY-----
    52  NHcCAQEEIHG5m/q2sUSa4P8pRZgYt3K0ESFSKp1qp15VjJhpLle4oAoGCCqGSM49AwEHoUQDQgAEvuynpVdR+5xSNaVBb//1fqO6Nb/nC+WvRQ4bALzy4G+QbByvO1Qpm2eUzTdDUnsLN5hp3pIXYAmtjvjY1fFZEg==
    53  -----END PRIVATE KEY-----
    54  `
    55  )
    56  
    57  func TestFromProto(t *testing.T) {
    58  	for _, test := range []struct {
    59  		desc     string
    60  		keyProto *keyspb.PEMKeyFile
    61  		wantErr  bool
    62  	}{
    63  		{
    64  			desc: "PEMKeyFile",
    65  			keyProto: &keyspb.PEMKeyFile{
    66  				Path:     "../../../testdata/log-rpc-server.privkey.pem",
    67  				Password: "towel",
    68  			},
    69  		},
    70  		{
    71  			desc: "PemKeyFile with non-existent file",
    72  			keyProto: &keyspb.PEMKeyFile{
    73  				Path: "non-existent.pem",
    74  			},
    75  			wantErr: true,
    76  		},
    77  		{
    78  			desc: "PemKeyFile with wrong password",
    79  			keyProto: &keyspb.PEMKeyFile{
    80  				Path:     "../../../testdata/log-rpc-server.privkey.pem",
    81  				Password: "wrong-password",
    82  			},
    83  			wantErr: true,
    84  		},
    85  		{
    86  			desc: "PemKeyFile with missing password",
    87  			keyProto: &keyspb.PEMKeyFile{
    88  				Path: "../../../testdata/log-rpc-server.privkey.pem",
    89  			},
    90  			wantErr: true,
    91  		},
    92  	} {
    93  		signer, err := FromProto(test.keyProto)
    94  		if gotErr := err != nil; gotErr != test.wantErr {
    95  			t.Errorf("%v: FromProto(%#v) = (_, %q), want (_, nil)", test.desc, test.keyProto, err)
    96  			continue
    97  		} else if gotErr {
    98  			continue
    99  		}
   100  
   101  		// Check that the returned signer can produce signatures successfully.
   102  		if err := ktestonly.SignAndVerify(signer, signer.Public()); err != nil {
   103  			t.Errorf("%v: SignAndVerify() = %q, want nil", test.desc, err)
   104  		}
   105  	}
   106  }
   107  
   108  func TestLoadPrivateKeyAndSign(t *testing.T) {
   109  	tests := []struct {
   110  		desc        string
   111  		keyPEM      string
   112  		keyPath     string
   113  		keyPass     string
   114  		wantLoadErr bool
   115  	}{
   116  		{
   117  			desc:    "ECDSA with password",
   118  			keyPEM:  testonly.DemoPrivateKey,
   119  			keyPass: testonly.DemoPrivateKeyPass,
   120  		},
   121  		{
   122  			desc:    "ECDSA from file with password",
   123  			keyPath: "../../../testdata/log-rpc-server.privkey.pem",
   124  			keyPass: "towel",
   125  		},
   126  		{
   127  			desc:        "Non-existent file",
   128  			keyPath:     "non-existent.pem",
   129  			wantLoadErr: true,
   130  		},
   131  		{
   132  			desc:        "ECDSA with wrong password",
   133  			keyPEM:      testonly.DemoPrivateKey,
   134  			keyPass:     testonly.DemoPrivateKeyPass + "foo",
   135  			wantLoadErr: true,
   136  		},
   137  		{
   138  			desc:   "ECDSA",
   139  			keyPEM: ecdsaPrivateKey,
   140  		},
   141  		{
   142  			desc:   "RSA",
   143  			keyPEM: rsaPrivateKey,
   144  		},
   145  		{
   146  			desc:   "ECDSA with leading junk",
   147  			keyPEM: "foobar\n" + ecdsaPrivateKey,
   148  		},
   149  		{
   150  			desc:        "ECDSA with trailing junk",
   151  			keyPEM:      ecdsaPrivateKey + "\nfoobar",
   152  			wantLoadErr: true,
   153  		},
   154  		{
   155  			desc:        "Corrupt ECDSA",
   156  			keyPEM:      corruptEcdsaPrivateKey,
   157  			wantLoadErr: true,
   158  		},
   159  	}
   160  
   161  	for _, test := range tests {
   162  		var k crypto.Signer
   163  		var err error
   164  		switch {
   165  		case test.keyPEM != "":
   166  			k, err = UnmarshalPrivateKey(test.keyPEM, test.keyPass)
   167  			switch gotErr := err != nil; {
   168  			case gotErr != test.wantLoadErr:
   169  				t.Errorf("%v: UnmarshalPrivateKey() = (%v, %v), want err? %v", test.desc, k, err, test.wantLoadErr)
   170  				continue
   171  			case gotErr:
   172  				continue
   173  			}
   174  
   175  		case test.keyPath != "":
   176  			k, err = ReadPrivateKeyFile(test.keyPath, test.keyPass)
   177  			switch gotErr := err != nil; {
   178  			case gotErr != test.wantLoadErr:
   179  				t.Errorf("%v: ReadPrivateKeyFile() = (%v, %v), want err? %v", test.desc, k, err, test.wantLoadErr)
   180  				continue
   181  			case gotErr:
   182  				continue
   183  			}
   184  
   185  		default:
   186  			t.Errorf("%v: No PEM or file path set in test definition", test.desc)
   187  			continue
   188  		}
   189  
   190  		// Check the key by creating a signature and verifying it.
   191  		if err := ktestonly.SignAndVerify(k, k.Public()); err != nil {
   192  			t.Errorf("%v: SignAndVerify() = %q, want nil", test.desc, err)
   193  		}
   194  	}
   195  }