1// Copyright 2012 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
5package x509
6
7import (
8	"bytes"
9	"crypto/rand"
10	"encoding/base64"
11	"encoding/pem"
12	"strings"
13	"testing"
14)
15
16func TestDecrypt(t *testing.T) {
17	for i, data := range testData {
18		t.Logf("test %v. %v", i, data.kind)
19		block, rest := pem.Decode(data.pemData)
20		if len(rest) > 0 {
21			t.Error("extra data")
22		}
23		der, err := DecryptPEMBlock(block, data.password)
24		if err != nil {
25			t.Error("decrypt failed: ", err)
26			continue
27		}
28		if _, err := ParsePKCS1PrivateKey(der); err != nil {
29			t.Error("invalid private key: ", err)
30		}
31		plainDER, err := base64.StdEncoding.DecodeString(data.plainDER)
32		if err != nil {
33			t.Fatal("cannot decode test DER data: ", err)
34		}
35		if !bytes.Equal(der, plainDER) {
36			t.Error("data mismatch")
37		}
38	}
39}
40
41func TestEncrypt(t *testing.T) {
42	for i, data := range testData {
43		t.Logf("test %v. %v", i, data.kind)
44		plainDER, err := base64.StdEncoding.DecodeString(data.plainDER)
45		if err != nil {
46			t.Fatal("cannot decode test DER data: ", err)
47		}
48		password := []byte("kremvax1")
49		block, err := EncryptPEMBlock(rand.Reader, "RSA PRIVATE KEY", plainDER, password, data.kind)
50		if err != nil {
51			t.Error("encrypt: ", err)
52			continue
53		}
54		if !IsEncryptedPEMBlock(block) {
55			t.Error("PEM block does not appear to be encrypted")
56		}
57		if block.Type != "RSA PRIVATE KEY" {
58			t.Errorf("unexpected block type; got %q want %q", block.Type, "RSA PRIVATE KEY")
59		}
60		if block.Headers["Proc-Type"] != "4,ENCRYPTED" {
61			t.Errorf("block does not have correct Proc-Type header")
62		}
63		der, err := DecryptPEMBlock(block, password)
64		if err != nil {
65			t.Error("decrypt: ", err)
66			continue
67		}
68		if !bytes.Equal(der, plainDER) {
69			t.Errorf("data mismatch")
70		}
71	}
72}
73
74var testData = []struct {
75	kind     PEMCipher
76	password []byte
77	pemData  []byte
78	plainDER string
79}{
80	{
81		kind:     PEMCipherDES,
82		password: []byte("asdf"),
83		pemData: []byte(testingKey(`
84-----BEGIN RSA TESTING KEY-----
85Proc-Type: 4,ENCRYPTED
86DEK-Info: DES-CBC,34F09A4FC8DE22B5
87
88WXxy8kbZdiZvANtKvhmPBLV7eVFj2A5z6oAxvI9KGyhG0ZK0skfnt00C24vfU7m5
89ICXeoqP67lzJ18xCzQfHjDaBNs53DSDT+Iz4e8QUep1xQ30+8QKX2NA2coee3nwc
906oM1cuvhNUDemBH2i3dKgMVkfaga0zQiiOq6HJyGSncCMSruQ7F9iWEfRbFcxFCx
91qtHb1kirfGKEtgWTF+ynyco6+2gMXNu70L7nJcnxnV/RLFkHt7AUU1yrclxz7eZz
92XOH9VfTjb52q/I8Suozq9coVQwg4tXfIoYUdT//O+mB7zJb9HI9Ps77b9TxDE6Gm
934C9brwZ3zg2vqXcwwV6QRZMtyll9rOpxkbw6NPlpfBqkc3xS51bbxivbO/Nve4KD
94r12ymjFNF4stXCfJnNqKoZ50BHmEEUDu5Wb0fpVn82XrGw7CYc4iug==
95-----END RSA TESTING KEY-----`)),
96		plainDER: `
97MIIBPAIBAAJBAPASZe+tCPU6p80AjHhDkVsLYa51D35e/YGa8QcZyooeZM8EHozo
98KD0fNiKI+53bHdy07N+81VQ8/ejPcRoXPlsCAwEAAQJBAMTxIuSq27VpR+zZ7WJf
99c6fvv1OBvpMZ0/d1pxL/KnOAgq2rD5hDtk9b0LGhTPgQAmrrMTKuSeGoIuYE+gKQ
100QvkCIQD+GC1m+/do+QRurr0uo46Kx1LzLeSCrjBk34wiOp2+dwIhAPHfTLRXS2fv
1017rljm0bYa4+eDZpz+E8RcXEgzhhvcQQ9AiAI5eHZJGOyml3MXnQjiPi55WcDOw0w
102glcRgT6QCEtz2wIhANSyqaFtosIkHKqrDUGfz/bb5tqMYTAnBruVPaf/WEOBAiEA
1039xORWeRG1tRpso4+dYy4KdDkuLPIO01KY6neYGm3BCM=`,
104	},
105	{
106		kind:     PEMCipher3DES,
107		password: []byte("asdf"),
108		pemData: []byte(testingKey(`
109-----BEGIN RSA TESTING KEY-----
110Proc-Type: 4,ENCRYPTED
111DEK-Info: DES-EDE3-CBC,C1F4A6A03682C2C7
112
1130JqVdBEH6iqM7drTkj+e2W/bE3LqakaiWhb9WUVonFkhyu8ca/QzebY3b5gCvAZQ
114YwBvDcT/GHospKqPx+cxDHJNsUASDZws6bz8ZXWJGwZGExKzr0+Qx5fgXn44Ms3x
1158g1ENFuTXtxo+KoNK0zuAMAqp66Llcds3Fjl4XR18QaD0CrVNAfOdgATWZm5GJxk
116Fgx5f84nT+/ovvreG+xeOzWgvtKo0UUZVrhGOgfKLpa57adumcJ6SkUuBtEFpZFB
117ldw5w7WC7d13x2LsRkwo8ZrDKgIV+Y9GNvhuCCkTzNP0V3gNeJpd201HZHR+9n3w
1183z0VjR/MGqsfcy1ziEWMNOO53At3zlG6zP05aHMnMcZoVXadEK6L1gz++inSSDCq
119gI0UJP4e3JVB7AkgYymYAwiYALAkoEIuanxoc50njJk=
120-----END RSA TESTING KEY-----`)),
121		plainDER: `
122MIIBOwIBAAJBANOCXKdoNS/iP/MAbl9cf1/SF3P+Ns7ZeNL27CfmDh0O6Zduaax5
123NBiumd2PmjkaCu7lQ5JOibHfWn+xJsc3kw0CAwEAAQJANX/W8d1Q/sCqzkuAn4xl
124B5a7qfJWaLHndu1QRLNTRJPn0Ee7OKJ4H0QKOhQM6vpjRrz+P2u9thn6wUxoPsef
125QQIhAP/jCkfejFcy4v15beqKzwz08/tslVjF+Yq41eJGejmxAiEA05pMoqfkyjcx
126fyvGhpoOyoCp71vSGUfR2I9CR65oKh0CIC1Msjs66LlfJtQctRq6bCEtFCxEcsP+
127eEjYo/Sk6WphAiEAxpgWPMJeU/shFT28gS+tmhjPZLpEoT1qkVlC14u0b3ECIQDX
128tZZZxCtPAm7shftEib0VU77Lk8MsXJcx2C4voRsjEw==`,
129	},
130	{
131		kind:     PEMCipherAES128,
132		password: []byte("asdf"),
133		pemData: []byte(testingKey(`
134-----BEGIN RSA TESTING KEY-----
135Proc-Type: 4,ENCRYPTED
136DEK-Info: AES-128-CBC,D4492E793FC835CC038A728ED174F78A
137
138EyfQSzXSjv6BaNH+NHdXRlkHdimpF9izWlugVJAPApgXrq5YldPe2aGIOFXyJ+QE
139ZIG20DYqaPzJRjTEbPNZ6Es0S2JJ5yCpKxwJuDkgJZKtF39Q2i36JeGbSZQIuWJE
140GZbBpf1jDH/pr0iGonuAdl2PCCZUiy+8eLsD2tyviHUkFLOB+ykYoJ5t8ngZ/B6D
14133U43LLb7+9zD4y3Q9OVHqBFGyHcxCY9+9Qh4ZnFp7DTf6RY5TNEvE3s4g6aDpBs
1423NbvRVvYTgs8K9EPk4K+5R+P2kD8J8KvEIGxVa1vz8QoCJ/jr7Ka2rvNgPCex5/E
143080LzLHPCrXKdlr/f50yhNWq08ZxMWQFkui+FDHPDUaEELKAXV8/5PDxw80Rtybo
144AVYoCVIbZXZCuCO81op8UcOgEpTtyU5Lgh3Mw5scQL0=
145-----END RSA TESTING KEY-----`)),
146		plainDER: `
147MIIBOgIBAAJBAMBlj5FxYtqbcy8wY89d/S7n0+r5MzD9F63BA/Lpl78vQKtdJ5dT
148cDGh/rBt1ufRrNp0WihcmZi7Mpl/3jHjiWECAwEAAQJABNOHYnKhtDIqFYj1OAJ3
149k3GlU0OlERmIOoeY/cL2V4lgwllPBEs7r134AY4wMmZSBUj8UR/O4SNO668ElKPE
150cQIhAOuqY7/115x5KCdGDMWi+jNaMxIvI4ETGwV40ykGzqlzAiEA0P9oEC3m9tHB
151kbpjSTxaNkrXxDgdEOZz8X0uOUUwHNsCIAwzcSCiGLyYJTULUmP1ESERfW1mlV78
152XzzESaJpIM/zAiBQkSTcl9VhcJreQqvjn5BnPZLP4ZHS4gPwJAGdsj5J4QIhAOVR
153B3WlRNTXR2WsJ5JdByezg9xzdXzULqmga0OE339a`,
154	},
155	{
156		kind:     PEMCipherAES192,
157		password: []byte("asdf"),
158		pemData: []byte(testingKey(`
159-----BEGIN RSA TESTING KEY-----
160Proc-Type: 4,ENCRYPTED
161DEK-Info: AES-192-CBC,E2C9FB02BCA23ADE1829F8D8BC5F5369
162
163cqVslvHqDDM6qwU6YjezCRifXmKsrgEev7ng6Qs7UmDJOpHDgJQZI9fwMFUhIyn5
164FbCu1SHkLMW52Ld3CuEqMnzWMlhPrW8tFvUOrMWPYSisv7nNq88HobZEJcUNL2MM
165Y15XmHW6IJwPqhKyLHpWXyOCVEh4ODND2nV15PCoi18oTa475baxSk7+1qH7GuIs
166Rb7tshNTMqHbCpyo9Rn3UxeFIf9efdl8YLiMoIqc7J8E5e9VlbeQSdLMQOgDAQJG
167ReUtTw8exmKsY4gsSjhkg5uiw7/ZB1Ihto0qnfQJgjGc680qGkT1d6JfvOfeYAk6
168xn5RqS/h8rYAYm64KnepfC9vIujo4NqpaREDmaLdX5MJPQ+SlytITQvgUsUq3q/t
169Ss85xjQEZH3hzwjQqdJvmA4hYP6SUjxYpBM+02xZ1Xw=
170-----END RSA TESTING KEY-----`)),
171		plainDER: `
172MIIBOwIBAAJBAMGcRrZiNNmtF20zyS6MQ7pdGx17aFDl+lTl+qnLuJRUCMUG05xs
173OmxmL/O1Qlf+bnqR8Bgg65SfKg21SYuLhiMCAwEAAQJBAL94uuHyO4wux2VC+qpj
174IzPykjdU7XRcDHbbvksf4xokSeUFjjD3PB0Qa83M94y89ZfdILIqS9x5EgSB4/lX
175qNkCIQD6cCIqLfzq/lYbZbQgAAjpBXeQVYsbvVtJrPrXJAlVVQIhAMXpDKMeFPMn
176J0g2rbx1gngx0qOa5r5iMU5w/noN4W2XAiBjf+WzCG5yFvazD+dOx3TC0A8+4x3P
177uZ3pWbaXf5PNuQIgAcdXarvhelH2w2piY1g3BPeFqhzBSCK/yLGxR82KIh8CIQDD
178+qGKsd09NhQ/G27y/DARzOYtml1NvdmCQAgsDIIOLA==`,
179	},
180	{
181		kind:     PEMCipherAES256,
182		password: []byte("asdf"),
183		pemData: []byte(testingKey(`
184-----BEGIN RSA TESTING KEY-----
185Proc-Type: 4,ENCRYPTED
186DEK-Info: AES-256-CBC,8E7ED5CD731902CE938957A886A5FFBD
187
1884Mxr+KIzRVwoOP0wwq6caSkvW0iS+GE2h2Ov/u+n9ZTMwL83PRnmjfjzBgfRZLVf
189JFPXxUK26kMNpIdssNnqGOds+DhB+oSrsNKoxgxSl5OBoYv9eJTVYm7qOyAFIsjr
190DRKAcjYCmzfesr7PVTowwy0RtHmYwyXMGDlAzzZrEvaiySFFmMyKKvtoavwaFoc7
191Pz3RZScwIuubzTGJ1x8EzdffYOsdCa9Mtgpp3L136+23dOd6L/qK2EG2fzrJSHs/
1922XugkleBFSMKzEp9mxXKRfa++uidQvMZTFLDK9w5YjrRvMBo/l2BoZIsq0jAIE1N
193sv5Z/KwlX+3MDEpPQpUwGPlGGdLnjI3UZ+cjgqBcoMiNc6HfgbBgYJSU6aDSHuCk
194clCwByxWkBNgJ2GrkwNrF26v+bGJJJNR4SKouY1jQf0=
195-----END RSA TESTING KEY-----`)),
196		plainDER: `
197MIIBOgIBAAJBAKy3GFkstoCHIEeUU/qO8207m8WSrjksR+p9B4tf1w5k+2O1V/GY
198AQ5WFCApItcOkQe/I0yZZJk/PmCqMzSxrc8CAwEAAQJAOCAz0F7AW9oNelVQSP8F
199Sfzx7O1yom+qWyAQQJF/gFR11gpf9xpVnnyu1WxIRnDUh1LZwUsjwlDYb7MB74id
200oQIhANPcOiLwOPT4sIUpRM5HG6BF1BI7L77VpyGVk8xNP7X/AiEA0LMHZtk4I+lJ
201nClgYp4Yh2JZ1Znbu7IoQMCEJCjwKDECIGd8Dzm5tViTkUW6Hs3Tlf73nNs65duF
202aRnSglss8I3pAiEAonEnKruawgD8RavDFR+fUgmQiPz4FnGGeVgfwpGG1JECIBYq
203PXHYtPqxQIbD2pScR5qum7iGUh11lEUPkmt+2uqS`,
204	},
205	{
206		// generated with:
207		// openssl genrsa -aes128 -passout pass:asdf -out server.orig.key 128
208		kind:     PEMCipherAES128,
209		password: []byte("asdf"),
210		pemData: []byte(testingKey(`
211-----BEGIN RSA TESTING KEY-----
212Proc-Type: 4,ENCRYPTED
213DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7
214
2156ei/MlytjE0FFgZOGQ+jrwomKfpl8kdefeE0NSt/DMRrw8OacHAzBNi3pPEa0eX3
216eND9l7C9meCirWovjj9QWVHrXyugFuDIqgdhQ8iHTgCfF3lrmcttVrbIfMDw+smD
217hTP8O1mS/MHl92NE0nhv0w==
218-----END RSA TESTING KEY-----`)),
219		plainDER: `
220MGMCAQACEQC6ssxmYuauuHGOCDAI54RdAgMBAAECEQCWIn6Yv2O+kBcDF7STctKB
221AgkA8SEfu/2i3g0CCQDGNlXbBHX7kQIIK3Ww5o0cYbECCQDCimPb0dYGsQIIeQ7A
222jryIst8=`,
223	},
224}
225
226var incompleteBlockPEM = testingKey(`
227-----BEGIN RSA TESTING KEY-----
228Proc-Type: 4,ENCRYPTED
229DEK-Info: AES-128-CBC,74611ABC2571AF11B1BF9B69E62C89E7
230
2316L8yXK2MTQUWBk4ZD6OvCiYp+mXyR1594TQ1K38MxGvDw5pwcDME2Lek8RrR5fd40P2XsL2Z4KKt
232ai+OP1BZUetfK6AW4MiqB2FDyIdOAJ8XeWuZy21Wtsh8wPD6yYOFM/w7WZL8weX3Y0TSeG/T
233-----END RSA TESTING KEY-----`)
234
235func TestIncompleteBlock(t *testing.T) {
236	// incompleteBlockPEM contains ciphertext that is not a multiple of the
237	// block size. This previously panicked. See #11215.
238	block, _ := pem.Decode([]byte(incompleteBlockPEM))
239	_, err := DecryptPEMBlock(block, []byte("foo"))
240	if err == nil {
241		t.Fatal("Bad PEM data decrypted successfully")
242	}
243	const expectedSubstr = "block size"
244	if e := err.Error(); !strings.Contains(e, expectedSubstr) {
245		t.Fatalf("Expected error containing %q but got: %q", expectedSubstr, e)
246	}
247}
248
249func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
250