Represents a JWE data structure.
        /// <summary>
        /// Creates an offline escrow entry for the master keys in the profile.
        /// </summary>
        /// <param name="Profile">The profile to create offline escrow entries for.</param>
        /// <param name="Shares">The total number of key shares to be created.</param>
        /// <param name="Quorum">The number of key shares required to recover the keys.</param>
        /// <returns></returns>

        public OfflineEscrowEntry(PersonalProfile Profile, int Shares, int Quorum) {
            var Master = Profile.PersonalMasterProfile;

            var EscrowedKeySet = new EscrowedKeySet();
            EscrowedKeySet.PrivateKeys = new List<Key>();

            EscrowedKeySet.PrivateKeys.Add(GetEscrow(
                Profile.PersonalMasterProfile.MasterSignatureKey.UDF));

            foreach (var Escrow in Profile.PersonalMasterProfile.MasterEscrowKeys) {
                EscrowedKeySet.PrivateKeys.Add(GetEscrow (Escrow.UDF));
                }




            var Encryptor = CryptoCatalog.Default.GetEncryption(
                            CryptoAlgorithmID.AES128CBC);

            var Secret = new Secret(Encryptor.Size);
            _KeyShares = Secret.Split(Shares, Quorum);

            //Trace.WriteHex("MasterKey", Secret.Key);
            //foreach (var share in _KeyShares) {
            //    Trace.WriteHex("Share", share.Key);
            //    }

            Encryptor.Key = Secret.Key;
            EncryptedData = new JoseWebEncryption (EscrowedKeySet.GetBytes(), Encryptor);


            Identifier = UDF.ToString (UDF.FromEscrowed(Secret.Key, 150));
            }
        public void JoseWebEncryptionTest() {

            var Plaintext = CryptoCatalog.GetBytes(2000);

            var Encrypted = new JoseWebEncryption(Plaintext);
            var Recovered = Encrypted.Decrypt();

            Trace.AssertEqual("Check Testvector", Plaintext, Recovered);
            }
        /// <summary>
        /// Encrypt the private data and create a decryption key for each device.
        /// </summary>
        public virtual void EncryptPrivate() {
            if (ApplicationProfileEntry == null) throw new Throw("Broken");
            if (ApplicationProfileEntry.DecryptID == null) throw new Throw("Broken");

            EncryptedData = new JoseWebEncryption(GetPrivateData);

            foreach (var Recipient in ApplicationProfileEntry.DecryptID) {
                // extract the device profile from the personal profile
                var SignedDeviceProfile = PersonalProfile.GetDeviceProfile(Recipient);
                var DeviceProfile = SignedDeviceProfile.Data;
                var EncryptionKey = DeviceProfile.DeviceEncryptiontionKey;

                // create a recipient entry

                EncryptedData.Add(EncryptionKey.KeyPair);
                }
            //Trace.NYI("Add entry here for the escrow key for this application");
            }
		/// <summary>
        /// Construct an instance from the specified tagged JSONReader stream.
        /// </summary>
        public static void Deserialize(JSONReader JSONReader, out JSONObject Out) {
	
			JSONReader.StartObject ();
            if (JSONReader.EOR) {
                Out = null;
                return;
                }

			string token = JSONReader.ReadToken ();
			Out = null;

			switch (token) {

				case "JoseWebSignature" : {
					var Result = new JoseWebSignature ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}


				case "JoseWebEncryption" : {
					var Result = new JoseWebEncryption ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}


				case "Signed" : {
					var Result = new Signed ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}


				case "Encrypted" : {
					var Result = new Encrypted ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}


				case "KeyData" : {
					var Result = new KeyData ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}


				case "Header" : {
					var Result = new Header ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}


				case "Key" : {
					var Result = new Key ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}


				case "Recipient" : {
					var Result = new Recipient ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}


				case "PublicKeyRSA" : {
					var Result = new PublicKeyRSA ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}


				case "PrivateKeyRSA" : {
					var Result = new PrivateKeyRSA ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}

				default : {
					throw new Exception ("Not supported");
					}
				}	
			JSONReader.EndObject ();
            }
        /// <summary>
        /// Deserialize a tagged stream
        /// </summary>
        /// <param name="JSONReader"></param>
        public static new JoseWebEncryption  FromTagged (JSONReader JSONReader) {
			JoseWebEncryption Out = null;

			JSONReader.StartObject ();
            if (JSONReader.EOR) {
                return null;
                }

			string token = JSONReader.ReadToken ();

			switch (token) {

				case "JoseWebEncryption" : {
					var Result = new JoseWebEncryption ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}

				default : {
					//Ignore the unknown data
                    //throw new Exception ("Not supported");
                    break;
					}
				}
			JSONReader.EndObject ();

			return Out;
			}
        /// <summary>
        /// Having read a tag, process the corresponding value data.
        /// </summary>
        /// <param name="JSONReader">The input stream</param>
        /// <param name="Tag">The tag</param>
		public override void DeserializeToken (JSONReader JSONReader, string Tag) {
			
			switch (Tag) {
				case "EncryptedData" : {
					// An untagged structure
					EncryptedData = new JoseWebEncryption (JSONReader);
 
					break;
					}
				default : {
					base.DeserializeToken(JSONReader, Tag);
					break;
					}
				}
			// check up that all the required elements are present
			}