/// <summary> /// Decrease the count of outstanding E-KEY interests for the C-KEY for /// timeCount. If the count decreases to 0, invoke onEncryptedKeys. /// </summary> /// /// <param name="keyRequest">The KeyRequest with the interestCount to update.</param> /// <param name="timeCount">The time count for indexing keyRequests_.</param> /// <param name="onEncryptedKeys_0">encrypted content key Data packets. If onEncryptedKeys is null, this does not use it.</param> private void updateKeyRequest(Producer.KeyRequest keyRequest, double timeCount, Producer.OnEncryptedKeys onEncryptedKeys_0) { --keyRequest.interestCount; if (keyRequest.interestCount == 0 && onEncryptedKeys_0 != null) { try { onEncryptedKeys_0.onEncryptedKeys(keyRequest.encryptedKeys); } catch (Exception exception) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE, "Error in onEncryptedKeys", exception); } ILOG.J2CsMapping.Collections.Collections.Remove(keyRequests_, timeCount); } }
/// <summary> /// This is called from an expressInterest OnData to check that the encryption /// key contained in data fits the timeSlot. This sends a refined interest if /// required. /// </summary> /// /// <param name="interest">The interest given to expressInterest.</param> /// <param name="data">The fetched Data packet.</param> /// <param name="timeSlot_0">The time slot as milliseconds since Jan 1, 1970 UTC.</param> /// <param name="onEncryptedKeys_1">encrypted content key Data packets. If onEncryptedKeys is null, this does not use it.</param> internal void handleCoveringKey(Interest interest, Data data, double timeSlot_0, Producer.OnEncryptedKeys onEncryptedKeys_1, net.named_data.jndn.encrypt.EncryptError.OnError onError_2) { double timeCount = Math.Round(timeSlot_0, MidpointRounding.AwayFromZero); Producer.KeyRequest keyRequest = (Producer.KeyRequest)ILOG.J2CsMapping.Collections.Collections.Get(keyRequests_, timeCount); Name interestName = interest.getName(); Name keyName = data.getName(); double begin = net.named_data.jndn.encrypt.Schedule.fromIsoString(keyName .get(START_TIME_STAMP_INDEX).getValue().toString()); double end = net.named_data.jndn.encrypt.Schedule.fromIsoString(keyName.get(END_TIME_STAMP_INDEX) .getValue().toString()); if (timeSlot_0 >= end) { // If the received E-KEY covers some earlier period, try to retrieve an // E-KEY covering a later one. Exclude timeRange = new Exclude(interest.getExclude()); excludeBefore(timeRange, keyName.get(START_TIME_STAMP_INDEX)); ILOG.J2CsMapping.Collections.Collections.Put(keyRequest.repeatAttempts, interestName, 0); sendKeyInterest(new Interest(interestName).setExclude(timeRange) .setChildSelector(1), timeSlot_0, onEncryptedKeys_1, onError_2); } else { // If the received E-KEY covers the content key, encrypt the content. Blob encryptionKey = data.getContent(); // If everything is correct, save the E-KEY as the current key. if (encryptContentKey(encryptionKey, keyName, timeSlot_0, onEncryptedKeys_1, onError_2)) { Producer.KeyInfo keyInfo = (Producer.KeyInfo)ILOG.J2CsMapping.Collections.Collections.Get(eKeyInfo_, interestName); keyInfo.beginTimeSlot = begin; keyInfo.endTimeSlot = end; keyInfo.keyBits = encryptionKey; } } }
/// <summary> /// This is called from an expressInterest timeout to update the state of /// keyRequest. Re-express the interest if the number of retrials is less than /// the max limit. /// </summary> /// /// <param name="interest">The timed-out interest.</param> /// <param name="timeSlot_0">The time slot as milliseconds since Jan 1, 1970 UTC.</param> /// <param name="onEncryptedKeys_1">encrypted content key Data packets. If onEncryptedKeys is null, this does not use it.</param> internal void handleTimeout(Interest interest, double timeSlot_0, Producer.OnEncryptedKeys onEncryptedKeys_1, net.named_data.jndn.encrypt.EncryptError.OnError onError_2) { double timeCount = Math.Round(timeSlot_0, MidpointRounding.AwayFromZero); Producer.KeyRequest keyRequest = (Producer.KeyRequest)ILOG.J2CsMapping.Collections.Collections.Get(keyRequests_, timeCount); Name interestName = interest.getName(); if ((int)(Int32)ILOG.J2CsMapping.Collections.Collections.Get(keyRequest.repeatAttempts, interestName) < maxRepeatAttempts_) { // Increase the retrial count. ILOG.J2CsMapping.Collections.Collections.Put(keyRequest.repeatAttempts, interestName, (int)(Int32)ILOG.J2CsMapping.Collections.Collections.Get(keyRequest.repeatAttempts, interestName) + 1); sendKeyInterest(interest, timeSlot_0, onEncryptedKeys_1, onError_2); } else { // No more retrials. updateKeyRequest(keyRequest, timeCount, onEncryptedKeys_1); } }
/// <summary> /// Get the content key from the database_ and encrypt it for the timeSlot /// using encryptionKey. /// </summary> /// /// <param name="encryptionKey">The encryption key value.</param> /// <param name="eKeyName">The key name for the EncryptedContent.</param> /// <param name="timeSlot_0">The time slot as milliseconds since Jan 1, 1970 UTC.</param> /// <param name="onEncryptedKeys_1">encrypted content key Data packets. If onEncryptedKeys is null, this does not use it.</param> /// <returns>True if encryption succeeds, otherwise false.</returns> private bool encryptContentKey(Blob encryptionKey, Name eKeyName, double timeSlot_0, Producer.OnEncryptedKeys onEncryptedKeys_1, net.named_data.jndn.encrypt.EncryptError.OnError onError_2) { double timeCount = Math.Round(timeSlot_0, MidpointRounding.AwayFromZero); Producer.KeyRequest keyRequest = (Producer.KeyRequest)ILOG.J2CsMapping.Collections.Collections.Get(keyRequests_, timeCount); Name keyName = new Name(namespace_); keyName.append(net.named_data.jndn.encrypt.algo.Encryptor.NAME_COMPONENT_C_KEY); keyName.append(net.named_data.jndn.encrypt.Schedule.toIsoString(getRoundedTimeSlot(timeSlot_0))); Blob contentKey = database_.getContentKey(timeSlot_0); Data cKeyData = new Data(); cKeyData.setName(keyName); EncryptParams paras = new EncryptParams(net.named_data.jndn.encrypt.algo.EncryptAlgorithmType.RsaOaep); try { net.named_data.jndn.encrypt.algo.Encryptor.encryptData(cKeyData, contentKey, eKeyName, encryptionKey, paras); } catch (Exception ex) { try { onError_2.onError(net.named_data.jndn.encrypt.EncryptError.ErrorCode.EncryptionFailure, ex.Message); } catch (Exception exception) { logger_.log(ILOG.J2CsMapping.Util.Logging.Level.SEVERE, "Error in onError", exception); } return(false); } keyChain_.sign(cKeyData); ILOG.J2CsMapping.Collections.Collections.Add(keyRequest.encryptedKeys, cKeyData); updateKeyRequest(keyRequest, timeCount, onEncryptedKeys_1); return(true); }
/// <summary> /// Create the content key corresponding to the timeSlot. This first checks if /// the content key exists. For an existing content key, this returns the /// content key name directly. If the key does not exist, this creates one and /// encrypts it using the corresponding E-KEYs. The encrypted content keys are /// passed to the onEncryptedKeys callback. /// </summary> /// /// <param name="timeSlot_0">The time slot as milliseconds since Jan 1, 1970 UTC.</param> /// <param name="onEncryptedKeys_1">content key Data packets. If onEncryptedKeys is null, this does not use it. NOTE: The library will log any exceptions thrown by this callback, but for better error handling the callback should catch and properly handle any exceptions.</param> /// <param name="onError_2">better error handling the callback should catch and properly handle any exceptions.</param> /// <returns>The content key name.</returns> public Name createContentKey(double timeSlot_0, Producer.OnEncryptedKeys onEncryptedKeys_1, net.named_data.jndn.encrypt.EncryptError.OnError onError_2) { double hourSlot = getRoundedTimeSlot(timeSlot_0); // Create the content key name. Name contentKeyName = new Name(namespace_); contentKeyName.append(net.named_data.jndn.encrypt.algo.Encryptor.NAME_COMPONENT_C_KEY); contentKeyName.append(net.named_data.jndn.encrypt.Schedule.toIsoString(hourSlot)); Blob contentKeyBits; // Check if we have created the content key before. if (database_.hasContentKey(timeSlot_0)) { // We have created the content key. Return its name directly. return(contentKeyName); } // We haven't created the content key. Create one and add it into the database. AesKeyParams aesParams = new AesKeyParams(128); contentKeyBits = net.named_data.jndn.encrypt.algo.AesAlgorithm.generateKey(aesParams).getKeyBits(); database_.addContentKey(timeSlot_0, contentKeyBits); // Now we need to retrieve the E-KEYs for content key encryption. double timeCount = Math.Round(timeSlot_0, MidpointRounding.AwayFromZero); ILOG.J2CsMapping.Collections.Collections.Put(keyRequests_, timeCount, new Producer.KeyRequest(eKeyInfo_.Count)); Producer.KeyRequest keyRequest = (Producer.KeyRequest)ILOG.J2CsMapping.Collections.Collections.Get(keyRequests_, timeCount); // Check if the current E-KEYs can cover the content key. Exclude timeRange = new Exclude(); excludeAfter(timeRange, new Name.Component(net.named_data.jndn.encrypt.Schedule.toIsoString(timeSlot_0))); new ILOG.J2CsMapping.Collections.IteratorAdapter(eKeyInfo_.GetEnumerator()); for (IIterator i = new ILOG.J2CsMapping.Collections.IteratorAdapter(eKeyInfo_.GetEnumerator()); i.HasNext();) { // For each current E-KEY. DictionaryEntry entry = (DictionaryEntry)i.Next(); Producer.KeyInfo keyInfo = (Producer.KeyInfo)((DictionaryEntry)entry).Value; if (timeSlot_0 < keyInfo.beginTimeSlot || timeSlot_0 >= keyInfo.endTimeSlot) { // The current E-KEY cannot cover the content key, so retrieve one. ILOG.J2CsMapping.Collections.Collections.Put(keyRequest.repeatAttempts, ((DictionaryEntry)entry).Key, 0); sendKeyInterest( new Interest((Name)((DictionaryEntry)entry).Key).setExclude( timeRange).setChildSelector(1), timeSlot_0, onEncryptedKeys_1, onError_2); } else { // The current E-KEY can cover the content key. // Encrypt the content key directly. Name eKeyName = new Name((Name)((DictionaryEntry)entry).Key); eKeyName.append(net.named_data.jndn.encrypt.Schedule.toIsoString(keyInfo.beginTimeSlot)); eKeyName.append(net.named_data.jndn.encrypt.Schedule.toIsoString(keyInfo.endTimeSlot)); encryptContentKey(keyInfo.keyBits, eKeyName, timeSlot_0, onEncryptedKeys_1, onError_2); } } return(contentKeyName); }