1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.crypto.store.filesystem.internal

File X509KeyFileSystemStore.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart8.png
54% of files have more coverage

Code metrics

32
65
8
1
222
162
31
0.48
8.12
8
3.88

Classes

Class Line # Actions
X509KeyFileSystemStore 54 65 0% 31 22
0.790476279%
 

Contributing tests

This file is covered by 13 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.crypto.store.filesystem.internal;
21   
22    import java.io.BufferedReader;
23    import java.io.BufferedWriter;
24    import java.io.File;
25    import java.io.FileReader;
26    import java.io.FileWriter;
27    import java.io.IOException;
28    import java.security.GeneralSecurityException;
29   
30    import javax.inject.Inject;
31    import javax.inject.Named;
32    import javax.inject.Singleton;
33   
34    import org.xwiki.component.annotation.Component;
35    import org.xwiki.crypto.AsymmetricKeyFactory;
36    import org.xwiki.crypto.params.cipher.asymmetric.PrivateKeyParameters;
37    import org.xwiki.crypto.password.PrivateKeyPasswordBasedEncryptor;
38    import org.xwiki.crypto.pkix.params.CertifiedKeyPair;
39    import org.xwiki.crypto.pkix.params.CertifiedPublicKey;
40    import org.xwiki.crypto.pkix.params.x509certificate.X509CertifiedPublicKey;
41    import org.xwiki.crypto.store.KeyStore;
42    import org.xwiki.crypto.store.KeyStoreException;
43    import org.xwiki.crypto.store.StoreReference;
44   
45    /**
46    * X509 implementation of {@link org.xwiki.crypto.store.KeyStore} for a wiki store.
47    *
48    * @version $Id: 35c25263878b3e687e167940cfc66f90a1f54753 $
49    * @since 6.1M2
50    */
51    @Component
52    @Named("X509file")
53    @Singleton
 
54    public class X509KeyFileSystemStore extends AbstractX509FileSystemStore implements KeyStore
55    {
56    private static final String PRIVATE_KEY = "PRIVATE KEY";
57   
58    private static final String ENCRYPTED_PRIVATE_KEY = "ENCRYPTED " + PRIVATE_KEY;
59   
60    /**
61    * Used to encrypt/decrypt private keys.
62    */
63    @Inject
64    private PrivateKeyPasswordBasedEncryptor encryptor;
65   
66    /**
67    * Used to create private key from encoded bytes.
68    */
69    @Inject
70    private AsymmetricKeyFactory keyFactory;
71   
 
72  3 toggle @Override
73    public void store(StoreReference store, CertifiedKeyPair keyPair) throws KeyStoreException
74    {
75  3 storeKeyPair(store, getPublicKey(keyPair.getCertificate()), keyPair.getPrivateKey().getEncoded(), PRIVATE_KEY);
76    }
77   
 
78  2 toggle @Override
79    public void store(StoreReference store, CertifiedKeyPair keyPair, byte[] password) throws KeyStoreException
80    {
81  2 byte[] key;
82   
83  2 try {
84  2 key = this.encryptor.encrypt(password, keyPair.getPrivateKey());
85    } catch (Exception e) {
86  0 throw new KeyStoreException(String.format("Error while encrypting private key to store a key pair in [%s]",
87    store), e);
88    }
89   
90  2 storeKeyPair(store, getPublicKey(keyPair.getCertificate()), key, ENCRYPTED_PRIVATE_KEY);
91    }
92   
 
93  5 toggle private void storeKeyPair(StoreReference store, X509CertifiedPublicKey certificate, byte[] privateKey, String type)
94    throws KeyStoreException
95    {
96  5 File file = getStoreFile(store);
97   
98  5 try {
99  5 if (isMulti(store)) {
100  3 if (!file.exists()) {
101  3 if (!file.mkdirs()) {
102  0 throw new KeyStoreException(String.format("Error while creating path [%s]", file));
103    }
104    }
105   
106  3 String filename = getCertIdentifier(certificate);
107  3 File keyfile = new File(file, filename + KEY_FILE_EXTENSION);
108  3 File certfile = new File(file, filename + CERTIFICATE_FILE_EXTENSION);
109   
110  3 store(new BufferedWriter(new FileWriter(keyfile)), type, privateKey);
111  3 store(new BufferedWriter(new FileWriter(certfile)), CERTIFICATE, certificate.getEncoded());
112    } else {
113  2 if (!file.exists()) {
114  2 if (!file.createNewFile()) {
115  0 throw new KeyStoreException(String.format("Error while creating file [%s]", file));
116    }
117    }
118   
119  2 BufferedWriter out = new BufferedWriter(new FileWriter(file));
120  2 write(out, type, privateKey);
121  2 store(out, CERTIFICATE, certificate.getEncoded());
122    }
123    } catch (IOException e) {
124  0 throw new KeyStoreException(String.format("Error while writing private key to file [%s]", file), e);
125    }
126    }
127   
 
128  3 toggle @Override
129    public CertifiedKeyPair retrieve(StoreReference store) throws KeyStoreException
130    {
131  3 return retrieve(store, (byte[]) null);
132    }
133   
 
134  4 toggle @Override
135    public CertifiedKeyPair retrieve(StoreReference store, byte[] password) throws KeyStoreException
136    {
137  4 File file = getStoreFile(store);
138   
139  4 if (isMulti(store)) {
140  0 throw new KeyStoreException(String.format("Unexpected store reference, [%s] should be single key store.",
141    file));
142    }
143   
144  4 X509CertifiedPublicKey cert = null;
145  4 PrivateKeyParameters key = null;
146   
147  4 try {
148  4 BufferedReader in = new BufferedReader(new FileReader(file));
149   
150  4 Object obj;
151  ? while ((obj = readObject(in, password)) != null) {
152  6 if (obj instanceof X509CertifiedPublicKey) {
153  3 cert = (X509CertifiedPublicKey) obj;
154  3 continue;
155    }
156  3 if (obj instanceof PrivateKeyParameters) {
157  3 key = ((PrivateKeyParameters) obj);
158    }
159    }
160    } catch (IOException e) {
161  0 throw new KeyStoreException(String.format("Error while reading from file [%s]", file), e);
162    } catch (GeneralSecurityException e) {
163  0 throw new KeyStoreException(String.format("Error while decrypting private key from file [%s]", file), e);
164    }
165   
166  4 if (key != null && cert != null) {
167  2 return new CertifiedKeyPair(key, cert);
168    }
169  2 return null;
170    }
171   
 
172  3 toggle @Override
173    public CertifiedKeyPair retrieve(StoreReference store, CertifiedPublicKey publicKey) throws KeyStoreException
174    {
175  3 return retrieve(store, publicKey, null);
176    }
177   
 
178  4 toggle @Override
179    public CertifiedKeyPair retrieve(StoreReference store, CertifiedPublicKey publicKey, byte[] password)
180    throws KeyStoreException
181    {
182  4 File file = getStoreFile(store);
183  4 X509CertifiedPublicKey certificate = getPublicKey(publicKey);
184   
185  4 if (!isMulti(store)) {
186  0 throw new KeyStoreException(String.format("Unexpected store reference, [%s] should be multi key store.",
187    file));
188    }
189   
190  4 try {
191  4 File keyfile = new File(file, getCertIdentifier(certificate) + KEY_FILE_EXTENSION);
192   
193  4 if (keyfile.exists()) {
194  3 BufferedReader in = new BufferedReader(new FileReader(keyfile));
195  3 Object obj;
196  ? while ((obj = readObject(in, password)) != null) {
197  3 if (obj instanceof PrivateKeyParameters) {
198  3 return new CertifiedKeyPair(((PrivateKeyParameters) obj), certificate);
199    }
200    }
201    }
202    } catch (IOException e) {
203  0 throw new KeyStoreException(String.format("Error while reading private key from store [%s]", file), e);
204    } catch (GeneralSecurityException e) {
205  0 throw new KeyStoreException(String.format("Error while decrypting private key from store [%s]", file), e);
206    }
207  1 return null;
208    }
209   
 
210  9 toggle @Override
211    protected Object processObject(BufferedReader in, String line, byte[] password)
212    throws IOException, GeneralSecurityException
213    {
214  9 if (line.contains(PEM_BEGIN + PRIVATE_KEY + DASHES)) {
215  4 return this.keyFactory.fromPKCS8(readBytes(in, PEM_END + PRIVATE_KEY + DASHES));
216    }
217  5 if (line.contains(PEM_BEGIN + ENCRYPTED_PRIVATE_KEY + DASHES)) {
218  2 return this.encryptor.decrypt(password, readBytes(in, PEM_END + ENCRYPTED_PRIVATE_KEY + DASHES));
219    }
220  3 return super.processObject(in, line, password);
221    }
222    }