/// <summary> /// Extract the next valid subkey set (Expired flag not set) as a KeyParam, and a CipherDescription structure. /// <para>Used only when calling a Encryption function.</para> /// </summary> /// /// <param name="Description">out: The CipherDescription structure; the properties required to create a specific cipher instance</param> /// <param name="KeyParam">out: The KeyParams class containing a unique key, initialization vector and HMAC key</param> /// /// <returns>The KeyId array used to identify a subkey set; set as the KeyId in a MessageHeader structure</returns> /// /// <exception cref="CryptoProcessingException">Thrown if the user has insufficient access rights to perform encryption with this key.</exception> public byte[] NextKey(out CipherDescription Description, out KeyParams KeyParam) { if (!AccessScope.Equals(KeyScope.Creator)) { throw new CryptoProcessingException("PackageFactory:NextKey", "You do not have permission to encrypt with this key!", new UnauthorizedAccessException()); } try { // get the key data MemoryStream keyStream = GetKeyStream(); // get the next unused key for encryption int index = PackageKey.NextSubkey(keyStream); if (index == -1) { throw new CryptoProcessingException("PackageFactory:NextKey", "The key file has expired! There are no keys left available for encryption.", new Exception()); } // get the cipher description Description = m_keyPackage.Description; // store the subkey identity, this is written into the message header to identify the subkey byte[] keyId = m_keyPackage.SubKeyID[index]; // get the starting position of the keying material within the package long keyPos = PackageKey.SubKeyOffset(keyStream, keyId); // no unused keys in the package file if (keyPos == -1) { throw new CryptoProcessingException("PackageFactory:NextKey", "The key file has expired! There are no keys left available for encryption.", new Exception()); } // get the keying material KeyParam = GetKeySet(keyStream, m_keyPackage.Description, keyPos); // mark the subkey as expired PackageKey.SubKeySetPolicy(keyStream, index, (long)PackageKeyStates.Expired); // write to file WriteKeyStream(keyStream); // return the subkey id return(keyId); } catch { throw; } }
/// <summary> /// Extract a subkey set (KeyParam), a file extension key, and a CipherDescription. /// <para>Used only when calling a Decryption function to get a specific subkey /// The KeyId field corresponds with the KeyId field contained in a MessageHeader structure.</para> /// </summary> /// /// <param name="KeyId">The KeyId array used to identify a subkey set; set as the KeyId in a MessageHeader structure</param> /// <param name="Description">out: The CipherDescription structure; the properties required to create a specific cipher instance</param> /// <param name="KeyParam">out: The KeyParams class containing a unique key, initialization vector and HMAC key</param> /// /// <exception cref="CryptoProcessingException">Thrown if the user has insufficient access rights to access this PackageKey, or the PackageKey does not contain the KeyId specified</exception> public void Extract(byte[] KeyId, out CipherDescription Description, out KeyParams KeyParam) { if (AccessScope.Equals(KeyScope.NoAccess)) { throw new CryptoProcessingException("PackageFactory:Extract", "You do not have permission to access this key!", new UnauthorizedAccessException()); } try { long keyPos; int index; // get the key data MemoryStream keyStream = GetKeyStream(); // get the keying materials starting offset within the key file keyPos = PackageKey.SubKeyOffset(keyStream, KeyId); if (keyPos == -1) { throw new CryptoProcessingException("PackageFactory:Extract", "This package does not contain the key file!", new ArgumentException()); } // get the index index = PackageKey.IndexFromId(keyStream, KeyId); // key flagged SingleUse was used for decryption and is locked out if (PackageKey.KeyHasPolicy(m_keyPackage.SubKeyPolicy[index], (long)PackageKeyStates.Locked) && !PackageKey.KeyHasPolicy(KeyPolicy, (long)KeyPolicies.VolumeKey)) { throw new CryptoProcessingException("PackageFactory:Extract", "SubKey is locked. The subkey has a single use policy and was previously used to decrypt the file.", new Exception()); } // key flagged PostOverwrite was used for decryption and was erased if (PackageKey.KeyHasPolicy(m_keyPackage.SubKeyPolicy[index], (long)PackageKeyStates.Erased)) { throw new CryptoProcessingException("PackageFactory:Extract", "SubKey is erased. The subkey has a post erase policy and was previously used to decrypt the file.", new Exception()); } // get the cipher description Description = m_keyPackage.Description; // get the keying material KeyParam = GetKeySet(keyStream, m_keyPackage.Description, keyPos); // test flags for overwrite or single use policies if (PackageKey.KeyHasPolicy(KeyPolicy, (long)KeyPolicies.PostOverwrite)) { PackageKey.SubKeySetPolicy(keyStream, index, (long)PackageKeyStates.Erased); } else if (PackageKey.KeyHasPolicy(KeyPolicy, (long)KeyPolicies.SingleUse)) { PackageKey.SubKeySetPolicy(keyStream, index, (long)PackageKeyStates.Locked); } // post overwrite flag set, erase the subkey if (PackageKey.KeyHasPolicy(KeyPolicy, (long)KeyPolicies.PostOverwrite)) { int keySize = Description.KeySize + Description.IvSize + Description.MacKeySize; // overwrite the region within file Erase(keyStream, keyPos, keySize); // clear this section of the key keyStream.Seek(keyPos, SeekOrigin.Begin); keyStream.Write(new byte[keySize], 0, keySize); } // write to file WriteKeyStream(keyStream); } catch { throw; } }