Describes a mesh device.
Inheritance: Profile
 /// <summary>
 /// Create a new device profile and persist it in the registry
 /// as the default profile.
 /// </summary>
 /// <param name="Name">Name of the device</param>
 /// <param name="Description">Description of the device.</param>
 public SignedDeviceProfile(string Name, string Description) {
     var Data = new DeviceProfile(Name, Description);
     Sign(Data);
     _Current = this;
     }
        /// <summary>
        /// Unpack the signed device profile data and verify it for
        /// consistency. Check the signature.
        /// </summary>
        /// <returns>The inner profile (if valid) otherwise null.</returns>
        public virtual DeviceProfile UnpackAndVerify() {
            var Text = Encoding.UTF8.GetString(SignedData.Payload);
            //Goedel.Debug.Trace.WriteLine("Data as signed {0}", Text);

            var Unpacked = DeviceProfile.FromTagged (Text);

            Unpacked.Unpack();

            var SigningKey = Unpacked.DeviceSignatureKey.KeyPair;
            var Verify = SignedData.Verify(Unpacked.UDF, SigningKey);
            Throw.IfNot(Verify, "Device signature does not verify");


            _Signed = Unpacked;
            return Unpacked;
            }
 /// <summary>
 /// Sign the device profile.
 /// </summary>
 /// <param name="Data">The device profile to sign.</param>
 public void Sign(DeviceProfile Data) {
     Identifier = Data.Identifier;  // pass through
     var PrivateKey = Data.DeviceSignatureKey.PrivateKey;
     SignedData = new JoseWebSignature(Data.GetBytes(), PrivateKey);
     _Signed = Data;
     }
        /// <summary>
        /// Deserialize the signed data.
        /// </summary>
        /// <returns>The device profile object.</returns>
        public DeviceProfile Unpack() {
            _Signed = null;

            var Reader = JSONReader.OfData(SignedData.Payload);
            var Profile = DeviceProfile.FromTagged(Reader);

            Throw.IfNot(Profile.DeviceSignatureKey.Verify(),
                    "Key fingerprint does not match key value");
            var PublicKey = Profile.DeviceSignatureKey.KeyPair;
            KeyNotFoundException.If(PublicKey == null);

            Throw.IfNot(SignedData.Verify(Profile.UDF, PublicKey), "Signature does not verify");

            _Signed = Profile;
            return _Signed;
            }
 /// <summary>
 /// Construct a signed profile from a device profile.
 /// </summary>
 /// <param name="Data">The device profile to sign.</param>
 public SignedDeviceProfile(DeviceProfile Data) {
     Sign(Data);
     }
		/// <summary>
        /// Construct an instance from the specified tagged JSONReader stream.
        /// </summary>
        /// <param name="JSONReader">Input stream</param>
        /// <param name="Out">The created object</param>
        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 "PublicKey" : {
					var Result = new PublicKey ();
					Result.Deserialize (JSONReader);
					Out = Result;
					break;
					}


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


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


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


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


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


				case "Profile" : {
					Out = null;
					throw new Exception ("Can't create abstract type");
					}


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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

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

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

			string token = JSONReader.ReadToken ();

			switch (token) {

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

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

			return Out;
			}
        /// <summary>
        /// Deserialize a tagged stream
        /// </summary>
        /// <param name="JSONReader">The input stream</param>
        /// <returns>The created object.</returns>		
        public static new Profile  FromTagged (JSONReader JSONReader) {
			Profile Out = null;

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

			string token = JSONReader.ReadToken ();

			switch (token) {

				case "Profile" : {
					Out = null;
					throw new Exception ("Can't create abstract type");
					}

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

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

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

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

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

			return Out;
			}
        /// <summary>
        /// Deserialize a tagged stream
        /// </summary>
        /// <param name="JSONReader">The input stream</param>
        /// <returns>The created object.</returns>		
        public static new Entry  FromTagged (JSONReader JSONReader) {
			Entry Out = null;

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

			string token = JSONReader.ReadToken ();

			switch (token) {

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

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

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

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

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

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

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

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

				case "Profile" : {
					Out = null;
					throw new Exception ("Can't create abstract type");
					}

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

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

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

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

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

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

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

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

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

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

			return Out;
			}