Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 97f1a2d3f7b4902eb601969143ae208e1e9372ed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
/*******************************************************************************
 * Copyright (c) 2008 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.equinox.security.storage;

import java.io.IOException;

/**
 * This interface describes functionality provided by secure preferences. Secure
 * preferences can be used to persist sensitive information in an encrypted form.
 * <p>
 * Logically, secure preferences combine functionality of a keyring (keystore) and 
 * {@link org.osgi.service.prefs.Preferences}.
 * </p><p>
 * For an excellent detailed description of the preferences functionality see
 * {@link org.osgi.service.prefs.Preferences}. To recap in a short form, preferences 
 * provide a tree. Nodes on that tree can be used to specify context. For instance, 
 * root node could have a child node called "cvs" to store information related to CVS 
 * integration.
 * </p><p>
 * Each node can have a map of keys with associated values. For instance, to store 
 * password for the CVS repository located on eclipse.org we could use the following 
 * code:
 * </p>
 * <pre>
 * 		ISecurePreferences root = SecurePreferencesFactory.getDefault();
 * 		ISecurePreferences node = root.node("cvs/eclipse.org");
 * 		node.put("password", myPassword, true);
 * </pre>
 * <p>
 * This interface has the following differences from the {@link org.osgi.service.prefs.Preferences}:</p>
 * <ul>
 * <li>get...() and put...() methods throw StorageException</li>
 * <li>put...() methods have an extra argument bEncrypt</li>
 * <li>Methods that used to throw BackingStoreException will be throwing more detailed StorageException</li> 
 * <li>Navigation on preferences tree will return ISecurePreferences, as opposing to Preferences</li>
 * <li>flush() throws IOException</li>
 * <li>sync() method is removed</li>
 * </ul> 
 * <p>
 * On the keyring side, when adding a key to the node, you can ask framework to encrypt it. Framework
 * will lazily acquire password from password provider and use it to encrypt all new  entries added 
 * to the secure preferences tree in this session. 
 * </p><p>
 * It is worthwhile to reiterate that same limitations as {@link org.osgi.service.prefs.Preferences}
 * apply to the node names. One non-trivial limitation is that node names can not contain forward 
 * slashes. For convenience, utility methods {@link EncodingUtils#encodeSlashes(String)} and
 * {@link EncodingUtils#decodeSlashes(String)} are provided to work around this limitation.
 * </p><p>
 * Also note that secure preferences only intended to store relatively small size data, such as 
 * passwords. If you need to securely store large objects, consider encrypting such objects in 
 * a symmetric way using randomly generated password and use secure preferences to store the password. 
 * </p><p>
 * If secure preferences were modified, the framework will automatically save them on shutdown.
 * </p><p>
 * This interface is not intended to be implemented or extended by clients.
 * </p>
 * @noextend This interface is not intended to be extended by clients.
 * @noimplement This interface is not intended to be implemented by clients.
 */
public interface ISecurePreferences {

	/**
	 * Stores a value associated with the key in this node. 
	 * @param key key with which the value is going to be associated
	 * @param value value to store
	 * @param encrypt <code>true</code> if value is to be encrypted, <code>false</code> value 
	 * does not need to be encrypted 
	 * @throws StorageException if exception occurred during encryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 * @throws NullPointerException if <code>key</code> is <code>null</code>.
	 */
	public void put(String key, String value, boolean encrypt) throws StorageException;

	/**
	 * Retrieves a value associated with the key in this node. If the value was encrypted,
	 * it is decrypted.
	 * @param key key with this the value is associated
	 * @param def default value to return if the key is not associated with any value
	 * @return value associated the key. If value was stored in an encrypted form, it will be decrypted
	 * @throws StorageException if exception occurred during decryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public String get(String key, String def) throws StorageException;

	/**
	 * Removes value associated with the key.
	 * @param key key with which a value is associated
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public void remove(String key);

	/**
	 * Removes all values from this node.
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public void clear();

	/**
	 * Returns keys that have associated values.
	 * @return keys that have associated values
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public String[] keys();

	/**
	 * Returns names of children nodes
	 * @return names of children nodes
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public String[] childrenNames();

	/**
	 * Returns parent of this node
	 * @return parent of this node
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public ISecurePreferences parent();

	/**
	 * Returns node corresponding to the path specified. If such node does not
	 * exist, a new node is created.
	 * <p>
	 * If the node path is invalid, an {@link IllegalArgumentException} will be thrown
	 * by this method. The valid node path:
	 * <ul>
	 * <li>contains only ASCII characters between 32 and 126 (ASCII alphanumeric and printable
	 * characters);</li>
	 * <li>can not contain two or more consecutive forward slashes;</li>
	 * <li>can not end with a trailing forward slash.</li>
	 * </ul>
	 * </p>
	 * @see org.osgi.service.prefs.Preferences
	 * @see org.osgi.service.prefs.Preferences#node(String)
	 * @param pathName absolute or relative path to the node
	 * @return node corresponding to the path
	 * @throws IllegalArgumentException if the path name is invalid.
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public ISecurePreferences node(String pathName);

	/**
	 * Checks if the node corresponding to the specified path exists in this tree
	 * of secure preferences.
	 * <p>
	 * If the node path is invalid, an {@link IllegalArgumentException} will be thrown
	 * by this method. See {@link #node(String)} for the description of what is considered
	 * to be a valid path.
	 * </p>
	 * @see org.osgi.service.prefs.Preferences
	 * @see org.osgi.service.prefs.Preferences#node(String)
	 * @param pathName absolute or relative path to the node
	 * @return <code>true</code> if node corresponding to the path exists, <code>false</code> otherwise 
	 * @throws IllegalArgumentException if the path name is invalid.
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public boolean nodeExists(String pathName);

	/**
	 * Removes this node from the tree of secure preferences.
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public void removeNode();

	/**
	 * Returns name of this node.
	 * @return name of this node
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public String name();

	/**
	 * Returns absolute path to this node.
	 * @return absolute path to this node
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public String absolutePath();

	/**
	 * Saves the tree of secure preferences to the persistent storage. This method can be called
	 * on any node in the secure preference tree.
	 * @throws IOException if error occurred while saving secure preferences
	 */
	public void flush() throws IOException;

	/**
	 * Stores a value associated with the key in this node. 
	 * @param key key with which the value is going to be associated
	 * @param value value to store
	 * @param encrypt <code>true</code> if value is to be encrypted, <code>false</code> value 
	 * does not need to be encrypted 
	 * @throws StorageException if exception occurred during encryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 * @throws NullPointerException if <code>key</code> is <code>null</code>.
	 */
	public void putInt(String key, int value, boolean encrypt) throws StorageException;

	/**
	 * Retrieves a value associated with the key in this node. If the value was encrypted,
	 * it is decrypted.
	 * @param key key with this the value is associated
	 * @param def default value to return if the key is not associated with any value
	 * @return value associated the key. If value was stored in an encrypted form, it will be decrypted
	 * @throws StorageException if exception occurred during decryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public int getInt(String key, int def) throws StorageException;

	/**
	 * Stores a value associated with the key in this node. 
	 * @param key key with which the value is going to be associated
	 * @param value value to store
	 * @param encrypt <code>true</code> if value is to be encrypted, <code>false</code> value 
	 * does not need to be encrypted 
	 * @throws StorageException if exception occurred during encryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 * @throws NullPointerException if <code>key</code> is <code>null</code>.
	 */
	public void putLong(String key, long value, boolean encrypt) throws StorageException;

	/**
	 * Retrieves a value associated with the key in this node. If the value was encrypted,
	 * it is decrypted.
	 * @param key key with this the value is associated
	 * @param def default value to return if the key is not associated with any value
	 * @return value associated the key. If value was stored in an encrypted form, it will be decrypted
	 * @throws StorageException if exception occurred during decryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public long getLong(String key, long def) throws StorageException;

	/**
	 * Stores a value associated with the key in this node. 
	 * @param key key with which the value is going to be associated
	 * @param value value to store
	 * @param encrypt <code>true</code> if value is to be encrypted, <code>false</code> value 
	 * does not need to be encrypted 
	 * @throws StorageException if exception occurred during encryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 * @throws NullPointerException if <code>key</code> is <code>null</code>.
	 */
	public void putBoolean(String key, boolean value, boolean encrypt) throws StorageException;

	/**
	 * Retrieves a value associated with the key in this node. If the value was encrypted,
	 * it is decrypted.
	 * @param key key with this the value is associated
	 * @param def default value to return if the key is not associated with any value
	 * @return value associated the key. If value was stored in an encrypted form, it will be decrypted
	 * @throws StorageException if exception occurred during decryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public boolean getBoolean(String key, boolean def) throws StorageException;

	/**
	 * Stores a value associated with the key in this node. 
	 * @param key key with which the value is going to be associated
	 * @param value value to store
	 * @param encrypt <code>true</code> if value is to be encrypted, <code>false</code> value 
	 * does not need to be encrypted 
	 * @throws StorageException if exception occurred during encryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 * @throws NullPointerException if <code>key</code> is <code>null</code>.
	 */
	public void putFloat(String key, float value, boolean encrypt) throws StorageException;

	/**
	 * Retrieves a value associated with the key in this node. If the value was encrypted,
	 * it is decrypted.
	 * @param key key with this the value is associated
	 * @param def default value to return if the key is not associated with any value
	 * @return value associated the key. If value was stored in an encrypted form, it will be decrypted
	 * @throws StorageException if exception occurred during decryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public float getFloat(String key, float def) throws StorageException;

	/**
	 * Stores a value associated with the key in this node. 
	 * @param key key with which the value is going to be associated
	 * @param value value to store
	 * @param encrypt <code>true</code> if value is to be encrypted, <code>false</code> value 
	 * does not need to be encrypted 
	 * @throws StorageException if exception occurred during encryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 * @throws NullPointerException if <code>key</code> is <code>null</code>.
	 */
	public void putDouble(String key, double value, boolean encrypt) throws StorageException;

	/**
	 * Retrieves a value associated with the key in this node. If the value was encrypted,
	 * it is decrypted.
	 * @param key key with this the value is associated
	 * @param def default value to return if the key is not associated with any value
	 * @return value associated the key. If value was stored in an encrypted form, it will be decrypted
	 * @throws StorageException if exception occurred during decryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public double getDouble(String key, double def) throws StorageException;

	/**
	 * Stores a value associated with the key in this node. 
	 * @param key key with which the value is going to be associated
	 * @param value value to store
	 * @param encrypt <code>true</code> if value is to be encrypted, <code>false</code> value 
	 * does not need to be encrypted 
	 * @throws StorageException if exception occurred during encryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 * @throws NullPointerException if <code>key</code> is <code>null</code>.
	 */
	public void putByteArray(String key, byte[] value, boolean encrypt) throws StorageException;

	/**
	 * Retrieves a value associated with the key in this node. If the value was encrypted,
	 * it is decrypted.
	 * @param key key with this the value is associated
	 * @param def default value to return if the key is not associated with any value
	 * @return value associated the key. If value was stored in an encrypted form, it will be decrypted
	 * @throws StorageException if exception occurred during decryption
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public byte[] getByteArray(String key, byte[] def) throws StorageException;

	/**
	 * Specifies if value associated with the key is encrypted.
	 * @param key key with which a value is associated
	 * @return <code>true</code> if value is encrypted, <code>false</code> otherwise
	 * @throws StorageException if stored data is invalid
	 * @throws IllegalStateException if this node (or an ancestor) has been removed with 
	 * the {@link #removeNode()} method.
	 */
	public boolean isEncrypted(String key) throws StorageException;
}

Back to the top