11package net .sharksystem .asap .crypto ;
22
3+ import net .sharksystem .SharkException ;
4+ import net .sharksystem .asap .ASAPException ;
35import net .sharksystem .asap .ASAPSecurityException ;
6+ import net .sharksystem .asap .utils .ASAPSerialization ;
7+ import net .sharksystem .fs .ExtraData ;
48import net .sharksystem .utils .Log ;
59
610import javax .crypto .SecretKey ;
711import java .io .*;
812import java .security .*;
913import java .security .spec .InvalidKeySpecException ;
14+ import java .security .spec .PKCS8EncodedKeySpec ;
1015import java .security .spec .X509EncodedKeySpec ;
1116import java .util .HashMap ;
1217
1318public class InMemoASAPKeyStore implements ASAPKeyStore {
19+ private PrivateKey privateKey ;
20+ private PublicKey publicKey ;
1421 private KeyPair keyPair ;
15- private final CharSequence ownerID ;
22+ private CharSequence ownerID ;
1623 private long keyPairCreationTime = 0 ;
1724
1825 // for debugging only - we don't have private key in real apps
@@ -35,10 +42,16 @@ public InMemoASAPKeyStore(CharSequence ownerID) throws ASAPSecurityException {
3542 * Setup key store with a key pair
3643 * @param ownerID
3744 * @param ownerKeyPair
45+ * @deprecated
3846 */
3947 public InMemoASAPKeyStore (CharSequence ownerID , KeyPair ownerKeyPair , long keyPairCreationTime ) {
4048 this .ownerID = ownerID ;
4149 this .keyPair = ownerKeyPair ;
50+ if (ownerKeyPair != null ) {
51+ this .privateKey = ownerKeyPair .getPrivate ();
52+ this .publicKey = ownerKeyPair .getPublic ();
53+ }
54+
4255 this .keyPairCreationTime = keyPairCreationTime ;
4356 }
4457
@@ -73,13 +86,12 @@ public int getSymmetricKeyLen() {
7386 return ASAPKeyStore .DEFAULT_SYMMETRIC_KEY_SIZE ;
7487 }
7588
76- private String getLogStart () {
77- return this .getClass ().getSimpleName () + ": " ;
78- }
79-
8089 public void generateKeyPair () throws ASAPSecurityException {
8190 this .setKeyPair (this .generateNewKeyPair ());
91+ this .privateKey = this .keyPair .getPrivate ();
92+ this .publicKey = this .keyPair .getPublic ();
8293 this .keyPairCreationTime = System .currentTimeMillis ();
94+ this .save ();
8395 }
8496
8597 private KeyPair generateNewKeyPair () throws ASAPSecurityException {
@@ -107,15 +119,22 @@ public KeyPair createTestPeer(String id) throws ASAPSecurityException {
107119 return keyPair ;
108120 }
109121
122+ private void checkKeyPairExistence () throws ASAPSecurityException {
123+ if (this .keyPair == null ) {
124+ Log .writeLog (this , "create new keypair since requested but missing" );
125+ this .generateKeyPair ();
126+ }
127+ }
128+
110129 @ Override
111130 public PrivateKey getPrivateKey () throws ASAPSecurityException {
112- if ( this .keyPair == null ) throw new ASAPSecurityException ( "private key does not exist" );
131+ this .checkKeyPairExistence ( );
113132 return this .keyPair .getPrivate ();
114133 }
115134
116135 @ Override
117136 public PublicKey getPublicKey () throws ASAPSecurityException {
118- if ( this .keyPair == null ) throw new ASAPSecurityException ( "private key does not exist" );
137+ this .checkKeyPairExistence ( );
119138 return this .keyPair .getPublic ();
120139 }
121140
@@ -184,7 +203,6 @@ public String getAsymmetricSigningAlgorithm() {
184203 }
185204
186205 public void addKeyPair (String peerID , KeyPair keyPair ) {
187-
188206 this .peerKeyPairs .put (peerID , keyPair );
189207 }
190208
@@ -242,4 +260,80 @@ public void readPublicKey(CharSequence peer, InputStream is) throws ASAPSecurity
242260 // store it
243261 this .putPublicKey (peer , publicKey );
244262 }
263+
264+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
265+ // persist //
266+ //////////////////////////////////////////////////////////////////////////////////////////////////////////////
267+
268+ private ExtraData mementoExtraData ;
269+ private CharSequence mementoKey ;
270+
271+ public void setMementoTarget (ExtraData extraData , CharSequence key ) {
272+ this .mementoExtraData = extraData ;
273+ this .mementoKey = key ;
274+ }
275+
276+ private void save () {
277+ if (this .mementoExtraData != null && this .mementoKey != null ) {
278+ try {
279+ this .mementoExtraData .putExtra (this .mementoKey , this .createMemento ());
280+ } catch (IOException | SharkException e ) {
281+ Log .writeLogErr (this , "cannot write memento: " + e .getLocalizedMessage ());
282+ }
283+ } else {
284+ Log .writeLog (this , "cannot write data - no persistent storage" );
285+ }
286+ }
287+
288+ byte [] createMemento () throws ASAPSecurityException , IOException {
289+ ByteArrayOutputStream baos = new ByteArrayOutputStream ();
290+
291+ // encoded private key
292+ ASAPSerialization .writeByteArray (this .getPrivateKey ().getEncoded (), baos );
293+ // private key algorithm
294+ ASAPSerialization .writeCharSequenceParameter (this .getPrivateKey ().getAlgorithm (), baos );
295+ // private key format
296+ ASAPSerialization .writeCharSequenceParameter (this .getPrivateKey ().getFormat (), baos );
297+
298+ // public key encoded
299+ ASAPSerialization .writeByteArray (this .getPublicKey ().getEncoded (), baos );
300+ // public key algorithm
301+ ASAPSerialization .writeCharSequenceParameter (this .getPublicKey ().getAlgorithm (), baos );
302+ // public key format
303+ ASAPSerialization .writeCharSequenceParameter (this .getPublicKey ().getFormat (), baos );
304+
305+ // creation time
306+ ASAPSerialization .writeLongParameter (this .keyPairCreationTime , baos );
307+
308+ // ownerID
309+ ASAPSerialization .writeCharSequenceParameter (this .ownerID , baos );
310+
311+ return baos .toByteArray ();
312+ }
313+
314+ public void restoreFromMemento (byte [] mementoData ) throws IOException , ASAPException {
315+ ByteArrayInputStream bais = new ByteArrayInputStream (mementoData );
316+
317+ byte [] privateKeyBytes = ASAPSerialization .readByteArray (bais );
318+ String privateKeyAlgorithm = ASAPSerialization .readCharSequenceParameter (bais );
319+ String privateKeyFormat = ASAPSerialization .readCharSequenceParameter (bais );
320+
321+ byte [] publicKeyBytes = ASAPSerialization .readByteArray (bais );
322+ String publicKeyAlgorithm = ASAPSerialization .readCharSequenceParameter (bais );
323+ String publicKeyFormat = ASAPSerialization .readCharSequenceParameter (bais );
324+
325+ // reproduce private key
326+ // as to be seen, pretty limited alg/format support yet :/
327+ try {
328+ KeyFactory kf = KeyFactory .getInstance ("RSA" );
329+ this .privateKey = kf .generatePrivate (new PKCS8EncodedKeySpec (privateKeyBytes ));
330+ this .publicKey = kf .generatePublic (new X509EncodedKeySpec (publicKeyBytes ));
331+ } catch (NoSuchAlgorithmException | InvalidKeySpecException e ) {
332+ throw new ASAPException ("cannot restore keystore form memento: " + e .getLocalizedMessage ());
333+ }
334+
335+ // reset those simple data after that critical stuff.
336+ this .keyPairCreationTime = ASAPSerialization .readLongParameter (bais );
337+ this .ownerID = ASAPSerialization .readCharSequenceParameter (bais );
338+ }
245339}
0 commit comments