6using System.Net.Http.Headers;
7using System.Runtime.ExceptionServices;
10using System.Threading.Tasks;
12using System.Xml.Schema;
136 private static readonly
string KeySettings = typeof(
ContractsClient).FullName +
".";
137 private static readonly
string ContractKeySettings = typeof(
ContractsClient).Namespace +
".Contracts.";
139 private const int CacheSchemaDays = 7;
143 private readonly Dictionary<string, KeyEventArgs> matchingKeys =
new Dictionary<string, KeyEventArgs>();
146 private DateTime keysTimestamp = DateTime.MinValue;
149 private readonly
string componentAddress;
150 private string keySettingsPrefix;
151 private string contractKeySettingsPrefix;
152 private bool keySettingsPrefixLocked =
false;
153 private bool useKeysForE2e =
false;
154 private bool preferredEncryptionAlgorithmLocked =
false;
155 private RandomNumberGenerator rnd = RandomNumberGenerator.Create();
158 private sealed
class LoadedKey : IDisposable
160 public LoadedKey(
IE2eEndpoint Endpoint,
bool MustDispose, DateTime Timestamp)
162 this.Endpoint = Endpoint;
163 this.MustDispose = MustDispose;
164 this.Timestamp = Timestamp;
168 public bool MustDispose {
get; }
169 public DateTime Timestamp {
get; }
171 public void Dispose()
173 if (this.MustDispose)
174 this.Endpoint?.Dispose();
178 private sealed
class LoadedKeySet : IDisposable
181 private bool transferred;
183 public LoadedKeySet(
IE2eEndpoint[] Keys, DateTime Timestamp)
186 this.Timestamp = Timestamp;
190 public DateTime Timestamp {
get; }
194 this.transferred =
true;
198 public void Dispose()
200 if (!this.transferred && !(this.keys is
null))
242 [Obsolete(
"Use overload with ICallStackCheck[] instead.")]
265 this.approvedSources = ApprovedSources;
266 this.SetLegalIdentityStateAllowedSources(ApprovedSources);
269 #region NeuroFoundation V1
272 this.
client.
RegisterMessageHandler(
"petitionIdentityMsg", NamespaceLegalIdentitiesNeuroFoundationV1, this.PetitionIdentityMessageHandler,
false);
273 this.
client.
RegisterMessageHandler(
"petitionIdentityResponseMsg", NamespaceLegalIdentitiesNeuroFoundationV1, this.PetitionIdentityResponseMessageHandler,
false);
274 this.
client.
RegisterMessageHandler(
"petitionSignatureMsg", NamespaceLegalIdentitiesNeuroFoundationV1, this.PetitionSignatureMessageHandler,
false);
275 this.
client.
RegisterMessageHandler(
"petitionSignatureResponseMsg", NamespaceLegalIdentitiesNeuroFoundationV1, this.PetitionSignatureResponseMessageHandler,
false);
276 this.
client.
RegisterMessageHandler(
"petitionClientUrl", NamespaceLegalIdentitiesNeuroFoundationV1, this.PetitionClientUrlEventHandler,
false);
277 this.
client.
RegisterMessageHandler(
"identityReview", NamespaceLegalIdentitiesNeuroFoundationV1, this.IdentityReviewEventHandler,
false);
280 this.
client.
RegisterMessageHandler(
"contractSigned", NamespaceSmartContractsNeuroFoundationV1, this.ContractSignedMessageHandler,
true);
281 this.
client.
RegisterMessageHandler(
"contractCreated", NamespaceSmartContractsNeuroFoundationV1, this.ContractCreatedMessageHandler,
false);
282 this.
client.
RegisterMessageHandler(
"contractUpdated", NamespaceSmartContractsNeuroFoundationV1, this.ContractUpdatedMessageHandler,
false);
283 this.
client.
RegisterMessageHandler(
"contractDeleted", NamespaceSmartContractsNeuroFoundationV1, this.ContractDeletedMessageHandler,
false);
284 this.
client.
RegisterMessageHandler(
"petitionContractMsg", NamespaceSmartContractsNeuroFoundationV1, this.PetitionContractMessageHandler,
false);
285 this.
client.
RegisterMessageHandler(
"petitionContractResponseMsg", NamespaceSmartContractsNeuroFoundationV1, this.PetitionContractResponseMessageHandler,
false);
286 this.
client.
RegisterMessageHandler(
"contractProposal", NamespaceSmartContractsNeuroFoundationV1, this.ContractProposalMessageHandler,
false);
294 this.
client.
RegisterMessageHandler(
"petitionIdentityResponseMsg", NamespaceLegalIdentitiesIeeeV1, this.PetitionIdentityResponseMessageHandler,
false);
295 this.
client.
RegisterMessageHandler(
"petitionSignatureMsg", NamespaceLegalIdentitiesIeeeV1, this.PetitionSignatureMessageHandler,
false);
296 this.
client.
RegisterMessageHandler(
"petitionSignatureResponseMsg", NamespaceLegalIdentitiesIeeeV1, this.PetitionSignatureResponseMessageHandler,
false);
306 this.
client.
RegisterMessageHandler(
"petitionContractResponseMsg", NamespaceSmartContractsIeeeV1, this.PetitionContractResponseMessageHandler,
false);
311 this.aes = Aes.Create();
312 this.aes.BlockSize = 128;
313 this.aes.KeySize = 256;
314 this.aes.Mode = CipherMode.CBC;
315 this.aes.Padding = PaddingMode.None;
317 this.keySettingsPrefix = KeySettings;
318 this.contractKeySettingsPrefix = ContractKeySettings;
326 #region NeuroFoundation V1
329 this.
client.
UnregisterMessageHandler(
"petitionIdentityMsg", NamespaceLegalIdentitiesNeuroFoundationV1, this.PetitionIdentityMessageHandler,
false);
330 this.
client.
UnregisterMessageHandler(
"petitionIdentityResponseMsg", NamespaceLegalIdentitiesNeuroFoundationV1, this.PetitionIdentityResponseMessageHandler,
false);
331 this.
client.
UnregisterMessageHandler(
"petitionSignatureMsg", NamespaceLegalIdentitiesNeuroFoundationV1, this.PetitionSignatureMessageHandler,
false);
332 this.
client.
UnregisterMessageHandler(
"petitionSignatureResponseMsg", NamespaceLegalIdentitiesNeuroFoundationV1, this.PetitionSignatureResponseMessageHandler,
false);
341 this.
client.
UnregisterMessageHandler(
"petitionContractMsg", NamespaceSmartContractsNeuroFoundationV1, this.PetitionContractMessageHandler,
false);
342 this.
client.
UnregisterMessageHandler(
"petitionContractResponseMsg", NamespaceSmartContractsNeuroFoundationV1, this.PetitionContractResponseMessageHandler,
false);
351 this.
client.
UnregisterMessageHandler(
"petitionIdentityResponseMsg", NamespaceLegalIdentitiesIeeeV1, this.PetitionIdentityResponseMessageHandler,
false);
353 this.
client.
UnregisterMessageHandler(
"petitionSignatureResponseMsg", NamespaceLegalIdentitiesIeeeV1, this.PetitionSignatureResponseMessageHandler,
false);
363 this.
client.
UnregisterMessageHandler(
"petitionContractResponseMsg", NamespaceSmartContractsIeeeV1, this.PetitionContractResponseMessageHandler,
false);
368 this.keys?.Dispose();
370 this.keysTimestamp = DateTime.MinValue;
423 if (this.preferredEncryptionAlgorithm == Algorithm)
426 if (this.preferredEncryptionAlgorithmLocked)
427 throw new InvalidOperationException(
"Preferred Encryptio Algorithm has been locked.");
429 this.preferredEncryptionAlgorithm = Algorithm;
430 this.preferredEncryptionAlgorithmLocked = Lock;
440 return this.
LoadKeys(CreateIfNone,
null);
452 return await this.LoadKeysLocked(CreateIfNone, Thread);
455 private static Task<Semaphore> LockKeys()
460 private async Task<bool> LoadKeysLocked(
bool CreateIfNone,
ProfilerThread Thread)
466 using LoadedKeySet LoadedKeys = await this.LoadPersistedKeysAsync(
467 CreateIfNone, Thread);
469 if (LoadedKeys is
null)
472 this.KeysLoaded(LoadedKeys);
482 private async Task<LoadedKeySet> LoadPersistedKeysAsync(
bool CreateIfNone,
ProfilerThread Thread)
486 List<IE2eEndpoint> Keys =
new List<IE2eEndpoint>();
492 int.MaxValue,
new Type[]
498 DateTime? Timestamp =
null;
505 foreach (KeyValuePair<string, object> Setting
in Settings)
507 string LocalName = Setting.Key[this.keySettingsPrefix.Length..];
509 if (Setting.Value is
string d)
511 if (
string.IsNullOrEmpty(d))
516 Key = Convert.FromBase64String(d);
539 else if (Setting.Value is DateTime TP && LocalName ==
"Timestamp")
543 if (Keys.Count == 0 || (Keys.Count != AvailableEndpoints.Length && CreateIfNone))
555 for (i = 0; i < c; i++)
557 if (Keys[i].LocalName == Endpoint.
LocalName)
565 Key = this.GetKey(Curve);
567 Key = this.GetKey(ModuleLattice);
575 Timestamp = DateTime.UtcNow;
580 else if (!Timestamp.HasValue)
584 Timestamp = DateTime.UtcNow;
588 return new LoadedKeySet(Keys.ToArray(), Timestamp.Value);
594 HashSet<IE2eEndpoint> LoadedEndpoints =
new HashSet<IE2eEndpoint>(Keys);
598 if (!LoadedEndpoints.Contains(Curve))
604 private void KeysLoaded(LoadedKeySet LoadedKeys)
606 if (!(this.keys is
null))
608 if (MatchesLoadedKeys(this.keys, LoadedKeys.Keys))
615 if (this.useKeysForE2e)
620 this.keysTimestamp = LoadedKeys.Timestamp;
622 this.ClearMatchingKeyCache();
625 private void ClearMatchingKeyCache()
627 lock (this.matchingKeys)
629 this.matchingKeys.Clear();
635 string s = EcEndpoint.
Curve.Export();
637 s = Doc.DocumentElement.GetAttribute(
"d");
638 return Convert.FromBase64String(s);
651 List<LegalIdentityState> ActiveStates = await this.GetActiveLegalIdentityStatesAsync(
false);
653 if (ActiveStates.Count == 0 &&
this.client.State ==
XmppState.Connected)
655 await this.TryRefreshLegalIdentityStatesAsync();
656 ActiveStates = await this.GetActiveLegalIdentityStatesAsync(
false);
662 await this.TryGetLegalIdentityEndpointAsync(State,
true,
true);
665 await this.LoadKeysLocked(
true,
null);
668 private async Task<List<LegalIdentityState>> GetActiveLegalIdentityStatesAsync(
bool RefreshStates)
670 List<LegalIdentityState> ActiveStates =
new List<LegalIdentityState>();
682 State.State = Identity.
State;
683 State.Timestamp = Identity.
Updated;
685 switch (Identity.
State)
690 State.PublicKey =
null;
713 ActiveStates.Add(State);
721 private async Task TryRefreshLegalIdentityStatesAsync()
733 private static byte[] Clone(
byte[] Bin)
735 return Bin is
null ? null : (
byte[])Bin.Clone();
738 private static bool AreEqual(
byte[] A,
byte[] B)
740 if (ReferenceEquals(A, B))
743 if (A is
null || B is
null || A.Length != B.Length)
748 for (i = 0; i < c; i++)
757 private bool TryExportPrivateKey(
IE2eEndpoint Endpoint, out
string KeyName, out
string KeyNamespace, out
byte[] PrivateKey)
766 PrivateKey = this.GetKey(Curve);
774 PrivateKey = Rsa.
Export(
true);
781 return !(PrivateKey is
null);
800 private async Task<Tuple<string, string, byte[]>> GetPersistablePrivateKeyAsync(
IE2eEndpoint Endpoint)
802 if (Endpoint is
null)
806 string KeyNamespace = Endpoint.
Namespace;
809 if (!
string.IsNullOrEmpty(RuntimeValue))
813 byte[] RuntimePrivateKey = Convert.FromBase64String(RuntimeValue);
820 if (AreEqual(RuntimeEndpoint.PublicKey, Endpoint.
PublicKey))
821 return new Tuple<
string,
string,
byte[]>(KeyName, KeyNamespace, RuntimePrivateKey);
831 return this.TryExportPrivateKey(Endpoint, out KeyName, out KeyNamespace, out
byte[] PrivateKey) ?
832 new Tuple<string, string, byte[]>(KeyName, KeyNamespace, PrivateKey)
840 string.IsNullOrEmpty(State.
KeyName))
845 string KeyNamespace =
string.IsNullOrEmpty(State.
KeyNamespace)
846 ? EndpointSecurity.IoTHarmonizationE2ECurrent
859 return Template.CreatePrivate(PrivateKey);
870 Tuple<string, string, byte[]> P = State is
null ? null : await this.GetPersistablePrivateKeyAsync(Endpoint);
877 string KeyName = P.Item1;
878 string KeyNamespace = P.Item2;
879 byte[] PrivateKey = P.Item3;
882 State.KeyName != KeyName ||
883 State.KeyNamespace != KeyNamespace ||
886 State.PublicKey = Clone(Endpoint.
PublicKey);
887 State.KeyName = KeyName;
888 State.KeyNamespace = KeyNamespace;
889 State.PrivateKey = Clone(PrivateKey);
894 private async Task<LoadedKey> TryGetLegalIdentityEndpointAsync(
LegalIdentityState State,
895 bool MigrateLegacyState,
bool Locked)
897 IE2eEndpoint Endpoint = this.TryCreateLegalIdentityEndpoint(State);
899 if (!(Endpoint is
null))
903 State.PublicKey = Clone(Endpoint.
PublicKey);
904 if (!
string.IsNullOrEmpty(State.
ObjectId))
907 return new LoadedKey(Endpoint,
true, State.
Timestamp);
915 return new LoadedKey(Endpoint,
true, State.
Timestamp);
919 string.IsNullOrEmpty(State.
KeyName);
921 if (!MigrateLegacyState ||
923 State?.PublicKey is
null ||
924 !(Locked ? await this.LoadKeysLocked(
false,
null) : await this.
LoadKeys(
false)))
926 return new LoadedKey(
null,
false, DateTime.MinValue);
930 if (Endpoint is
null ||
931 !await this.SetLegalIdentityKeySnapshotAsync(State, Endpoint))
933 return new LoadedKey(Endpoint,
false, State.
Timestamp);
936 if (!
string.IsNullOrEmpty(State.
ObjectId))
939 IE2eEndpoint Endpoint2 = this.TryCreateLegalIdentityEndpoint(State);
940 return Endpoint2 is
null
941 ?
new LoadedKey(Endpoint,
false, State.
Timestamp)
942 : new LoadedKey(Endpoint2, true, State.Timestamp);
946 out
string CreatorJid, out
byte[] SharedSecret)
949 CreatorJid =
string.Empty;
952 if (
string.IsNullOrEmpty(Value))
955 string[] Parts = Value.Split(
'|');
956 if (Parts.Length != 3 || !Enum.TryParse(Parts[0], out Algorithm))
959 CreatorJid = Parts[1];
963 SharedSecret = Convert.FromBase64String(Parts[2]);
973 private static Tuple<SymmetricCipherAlgorithms, string, byte[]> CreateContractSharedSecretTuple(
976 if (SharedSecret is
null)
979 return new Tuple<SymmetricCipherAlgorithms, string, byte[]>(Algorithm, CreatorJid ??
string.Empty,
980 (
byte[])SharedSecret.Clone());
983 private static string EncodeContractSharedSecret(
SymmetricCipherAlgorithms Algorithm,
string CreatorJid,
byte[] SharedSecret)
985 if (SharedSecret is
null)
988 return Algorithm.ToString() +
"|" + (CreatorJid ??
string.Empty) +
"|" + Convert.ToBase64String(SharedSecret);
991 private async Task<ContractSharedSecretState> GetContractStateAsync(
string ContractId)
998 private async Task<bool> UpsertContractStateAsync(
string ContractId,
string CreatorJid,
byte[] SharedSecret,
1001 if (
string.IsNullOrEmpty(ContractId) || SharedSecret is
null)
1005 byte[] SecretCopy = (
byte[])SharedSecret.Clone();
1012 CreatorJid = CreatorJid ??
string.Empty,
1013 KeyAlgorithm = KeyAlgorithm,
1014 SharedSecret = SecretCopy
1021 State.CreatorJid = CreatorJid ??
string.Empty;
1022 State.KeyAlgorithm = KeyAlgorithm;
1023 State.SharedSecret = SecretCopy;
1039 private async Task<Tuple<SymmetricCipherAlgorithms, string, byte[]>> TryLoadLegacyContractSharedSecretAsync(
1040 string ContractId,
bool MigrateToState)
1042 string Name = this.contractKeySettingsPrefix + ContractId;
1046 out
byte[] SharedSecret))
1052 await this.UpsertContractStateAsync(ContractId, CreatorJid, SharedSecret, Algorithm);
1054 return CreateContractSharedSecretTuple(Algorithm, CreatorJid, SharedSecret);
1057 private async Task<List<ContractSharedSecretState>> GetExportableContractStatesAsync()
1059 Dictionary<string, ContractSharedSecretState> ContractStates =
new Dictionary<string, ContractSharedSecretState>(StringComparer.Ordinal);
1060 List<ContractSharedSecretState> Result =
new List<ContractSharedSecretState>();
1072 foreach (KeyValuePair<string, object> Setting
in Settings)
1074 if (!(Setting.Value is
string Value))
1077 string ContractId = Setting.Key[this.contractKeySettingsPrefix.Length..];
1079 if (ContractStates.ContainsKey(ContractId) ||
1081 out
byte[] SharedSecret))
1086 if (await this.UpsertContractStateAsync(ContractId, CreatorJid, SharedSecret, Algorithm))
1090 if (!(State is
null))
1091 ContractStates[ContractId] = State;
1107 StringBuilder Xml =
new StringBuilder();
1110 using (XmlWriter Output = XmlWriter.Create(Xml, Settings))
1115 return Xml.ToString();
1124 this.AssertAllowed();
1130 foreach (KeyValuePair<string, object> Setting
in Settings)
1132 string Name = Setting.Key[this.keySettingsPrefix.Length..];
1134 if (Setting.Value is
string s)
1136 Output.WriteStartElement(
"S");
1137 Output.WriteAttributeString(
"n", Name);
1138 Output.WriteAttributeString(
"v", s);
1139 Output.WriteEndElement();
1141 else if (Setting.Value is DateTime TP)
1143 Output.WriteStartElement(
"DT");
1144 Output.WriteAttributeString(
"n", Name);
1145 Output.WriteAttributeString(
"v",
XML.
Encode(TP));
1146 Output.WriteEndElement();
1154 using LoadedKey Key = await this.TryGetLegalIdentityEndpointAsync(State,
true,
false);
1157 if (Endpoint is
null || State.PublicKey is
null || !State.HasPrivateKey ||
string.IsNullOrEmpty(State.KeyName))
1160 Output.WriteStartElement(
"State");
1161 Output.WriteAttributeString(
"legalId", State.LegalId);
1162 Output.WriteAttributeString(
"publicKey", Convert.ToBase64String(State.PublicKey));
1163 Output.WriteAttributeString(
"timestamp",
XML.
Encode(State.Timestamp));
1164 Output.WriteAttributeString(
"keyName", State.KeyName);
1166 if (!
string.IsNullOrEmpty(State.KeyNamespace))
1167 Output.WriteAttributeString(
"keyNamespace", State.KeyNamespace);
1169 Output.WriteAttributeString(
"hasPrivateKey",
CommonTypes.
Encode(State.HasPrivateKey));
1170 Output.WriteAttributeString(
"privateKey", Convert.ToBase64String(State.PrivateKey));
1171 Output.WriteEndElement();
1179 Output.WriteStartElement(
"C");
1181 Output.WriteAttributeString(
"v", EncodeContractSharedSecret(
ContractState.KeyAlgorithm,
1183 Output.WriteEndElement();
1186 Output.WriteEndElement();
1218 this.AssertAllowed();
1223 foreach (XmlNode N
in Xml.ChildNodes)
1225 if (!(N is XmlElement E))
1231 switch (E.LocalName)
1242 DateTime DateTimeValue =
XML.
Attribute(E,
"v", DateTime.MinValue);
1253 out
string CreatorJid, out
byte[] SharedSecret))
1258 if (!await this.UpsertContractStateAsync(Name, CreatorJid, SharedSecret, ContractAlgorithm))
1263 case "ContractState":
1267 string KeyAlgorithm =
XML.
Attribute(E,
"keyAlgorithm");
1268 string SharedSecretStr =
XML.
Attribute(E,
"sharedSecret");
1269 byte[] SharedSecret;
1276 SharedSecret = Convert.FromBase64String(SharedSecretStr);
1283 if (!await this.UpsertContractStateAsync(ContractId, CreatorJid, SharedSecret, ContractAlgorithm))
1293 string KeyNamespace =
XML.
Attribute(E,
"keyNamespace");
1295 byte[] PrivateKey =
null;
1296 DateTimeValue =
XML.
Attribute(E,
"timestamp", DateTime.MinValue);
1300 PublicKey = Convert.FromBase64String(PublicKeyStr);
1307 if (!
string.IsNullOrEmpty(PrivateKeyStr))
1311 PrivateKey = Convert.FromBase64String(PrivateKeyStr);
1323 if (IdState is
null)
1330 Timestamp = DateTimeValue,
1331 PublicKey = PublicKey,
1333 KeyNamespace = KeyNamespace,
1334 PrivateKey = PrivateKey
1342 IdState.Timestamp = DateTimeValue;
1343 IdState.PublicKey = PublicKey;
1344 IdState.KeyName = KeyName;
1345 IdState.KeyNamespace = KeyNamespace;
1346 IdState.PrivateKey = PrivateKey;
1364 using LoadedKey Key = await this.TryGetLegalIdentityEndpointAsync(State,
true,
false);
1366 if (!(Key.Endpoint is
null))
1380 if (this.keySettingsPrefixLocked)
1381 throw new InvalidOperationException(
"Key settings instance is locked.");
1383 if (
string.IsNullOrEmpty(InstanceName))
1385 this.keySettingsPrefix = KeySettings;
1386 this.contractKeySettingsPrefix = ContractKeySettings;
1390 this.keySettingsPrefix = InstanceName +
"." + KeySettings;
1391 this.contractKeySettingsPrefix = InstanceName +
"." + ContractKeySettings;
1394 this.keySettingsPrefixLocked = Locked;
1403 using Semaphore Lock = await LockKeys();
1405 if (this.useKeysForE2e)
1408 this.useKeysForE2e =
true;
1410 if (this.keys is
null)
1411 await this.LoadKeysLocked(
true,
null);
1413 if (this.keys.Client is
null)
1414 this.keys.RegisterHandlers(this.
client);
1423 using Semaphore Lock = await LockKeys();
1425 if (!this.useKeysForE2e)
1428 this.useKeysForE2e =
false;
1429 this.keys?.UnregisterHandlers(this.
client);
1446 throw new ArgumentException(nameof(Nr));
1448 byte[] Bytes =
new byte[Nr];
1450 this.rnd.GetBytes(Bytes);
1462 return BitConverter.ToUInt64(Bin, 0);
1472 if (MaxExclusive == 0)
1473 throw new ArgumentException(nameof(MaxExclusive));
1488 if (MaxInclusive < MinInclusive)
1489 throw new ArgumentException(nameof(MaxInclusive));
1491 ulong Diff = (uint)(MaxInclusive - MinInclusive);
1493 return MinInclusive;
1496 Result += MinInclusive;
1510 [Obsolete(
"Use the overload taking ICallStackCheck instances instead.")]
1523 if (!(this.approvedSources is
null))
1524 throw new NotSupportedException(
"Changing approved sources not permitted.");
1526 this.approvedSources = ApprovedSources;
1527 this.SetLegalIdentityStateAllowedSources(ApprovedSources);
1528 this.SetContractStateAllowedSources(ApprovedSources);
1531 private void AssertAllowed()
1533 if (!(this.approvedSources is
null))
1537 private void SetLegalIdentityStateAllowedSources(
ICallStackCheck[] ApprovedSources)
1539 if (ApprovedSources is
null)
1546 catch (NotSupportedException)
1552 private void SetContractStateAllowedSources(
ICallStackCheck[] ApprovedSources)
1554 if (ApprovedSources is
null)
1561 catch (NotSupportedException)
1578 return "iotid:" + LegalId;
1598 return "iotsc:" + ContractId;
1613 #region Server Public Keys
1632 EventHandlerAsync<KeyEventArgs> Callback,
object State)
1656 EventHandlerAsync<KeyEventArgs> Callback,
object State)
1658 if (this.publicKeys.TryGetRecord(Address, Timestamp ?? DateTime.UtcNow,
1666 await Callback.Raise(
this, e0);
1674 await h.Raise(
this, e,
false);
1678 if (!(Callback is
null))
1680 XmlDocument Doc =
new XmlDocument();
1681 XmlElement Empty = Doc.CreateElement(
"Local");
1685 await Callback.Raise(
this, e2);
1692 StringBuilder sb =
new StringBuilder();
1694 sb.Append(
"<getPublicKey xmlns=\"");
1697 if (Timestamp.HasValue)
1699 sb.Append(
"\" ts=\"");
1700 sb.Append(
XML.
Encode(Timestamp.Value.ToUniversalTime()));
1705 await this.
client.
SendIqGet(Address, sb.ToString(), async (Sender, e) =>
1709 DateTime? From =
null;
1710 DateTime? To =
null;
1713 !((E = e.FirstElement) is
null) &&
1714 E.LocalName ==
"publicKey")
1716 From = XML.Attribute(E,
"from", DateTime.MinValue);
1717 To = E.HasAttribute(
"to") ?
1718 XML.Attribute(E,
"to", DateTime.MaxValue) : (DateTime?)null;
1720 foreach (XmlNode N in E.ChildNodes)
1722 if (N is XmlElement E2)
1724 ServerKey = EndpointSecurity.ParseE2eKey(E2);
1725 if (!(ServerKey is null))
1730 e.Ok = !(ServerKey is
null);
1735 e0 =
new KeyEventArgs(e, ServerKey, From ?? DateTime.MinValue, To);
1739 this.publicKeys.Add(Address, From ?? DateTime.MinValue,
1740 To ?? DateTime.UtcNow, e0);
1743 await Callback.Raise(
this, e0);
1752 public static event EventHandlerAsync<PublicKeyEventArgs> GetLocalPublicKey =
null;
1760 return this.GetServerPublicKeyAsync(this.componentAddress);
1770 TaskCompletionSource<IE2eEndpoint> Result =
new TaskCompletionSource<IE2eEndpoint>();
1772 await this.GetServerPublicKey(Address, (Sender, e) =>
1775 Result.TrySetResult(e.Key);
1777 Result.TrySetException(e.StanzaError ??
new Exception(
"Unable to get public key."));
1779 return Task.CompletedTask;
1783 return await Result.Task;
1788 #region Matching Local Keys
1797 return this.GetMatchingLocalKey(this.componentAddress, Callback, State);
1807 if (this.keys is
null)
1808 throw new InvalidOperationException(
"Local keys not loaded or generated.");
1824 lock (this.matchingKeys)
1826 if (!this.matchingKeys.TryGetValue(Address, out e0))
1837 await Callback.Raise(
this, e0);
1841 await this.GetServerPublicKey(Address, async (Sender, e) =>
1847 LocalKey = this.LocalEndpoint.FindLocalEndpoint(e.Key);
1848 if (LocalKey is null)
1852 e0 =
new KeyEventArgs(e, LocalKey, e.ValidFrom, e.ValidTo);
1856 lock (this.matchingKeys)
1858 this.matchingKeys[Address] = e0;
1862 await Callback.Raise(
this, e0);
1874 return this.GetMatchingLocalKeyAsync(this.componentAddress);
1884 TaskCompletionSource<IE2eEndpoint> Result =
new TaskCompletionSource<IE2eEndpoint>();
1886 await this.GetMatchingLocalKey(Address, (Sender, e) =>
1889 Result.TrySetResult(e.Key);
1891 Result.TrySetException(e.StanzaError ??
new Exception(
"Unable to get matching local key."));
1893 return Task.CompletedTask;
1897 return await Result.Task;
1902 #region ID Application Attributes
1911 return this.client.SendIqGet(this.componentAddress,
"<applicationAttributes xmlns='" + NamespaceLegalIdentitiesCurrent +
"'/>", (Sender, e) =>
1924 TaskCompletionSource<IdApplicationAttributesEventArgs> Result =
new TaskCompletionSource<IdApplicationAttributesEventArgs>();
1926 await this.GetIdApplicationAttributes((Sender, e) =>
1929 Result.TrySetResult(e);
1931 Result.TrySetException(e.StanzaError ??
new Exception(
"Unable to get ID Application attributes."));
1933 return Task.CompletedTask;
1936 return await Result.Task;
1941 #region Apply for a Legal Identity
1949 public Task
Apply(
Property[] Properties, EventHandlerAsync<LegalIdentityEventArgs> Callback,
object State)
1951 return this.Apply(this.componentAddress, Properties,
false, Callback, State);
1961 public Task
Apply(
string Address,
Property[] Properties, EventHandlerAsync<LegalIdentityEventArgs> Callback,
object State)
1963 return this.Apply(Address, Properties,
false, Callback, State);
1974 public Task
Apply(
Property[] Properties,
bool Preview, EventHandlerAsync<LegalIdentityEventArgs> Callback,
object State)
1976 return this.Apply(this.componentAddress, Properties, Preview, Callback, State);
1989 EventHandlerAsync<LegalIdentityEventArgs> Callback,
object State)
1991 this.AssertAllowed();
1993 await this.GetMatchingLocalKey(Address, async (Sender, e) =>
1997 StringBuilder Xml = new StringBuilder();
1999 Xml.Append(
"<apply xmlns=\"");
2000 Xml.Append(NamespaceLegalIdentitiesCurrent);
2003 Xml.Append(
"\" preview=\"true");
2007 StringBuilder Identity = new StringBuilder();
2009 Identity.Append(
"<identity><clientPublicKey>");
2010 e.Key.ToXml(Identity, NamespaceLegalIdentitiesCurrent);
2011 Identity.Append(
"</clientPublicKey>");
2013 foreach (Property Property in Properties)
2015 Identity.Append(
"<property name=\"");
2016 Identity.Append(XML.Encode(Property.Name));
2017 Identity.Append(
"\" value=\"");
2018 Identity.Append(XML.Encode(Property.Value));
2019 Identity.Append(
"\"/>");
2022 string s = Identity.ToString();
2027 byte[] Bin = Encoding.UTF8.GetBytes(s);
2030 Xml.Append(
"<clientSignature>");
2031 Xml.Append(Convert.ToBase64String(
Signature));
2032 Xml.Append(
"</clientSignature>");
2034 Xml.Append(
"</identity></apply>");
2036 await
this.client.SendIqSet(Address, Xml.ToString(), async (sender2, e2) =>
2041 if (e2.Ok && !((E = e2.FirstElement) is
null) &&
2042 E.LocalName ==
"identity")
2044 Identity2 = LegalIdentity.Parse(E);
2045 await this.UpdateSettings(Identity2, e.Key.PublicKey);
2065 return this.ApplyAsync(this.componentAddress, Properties,
false);
2076 return this.ApplyAsync(Address, Properties,
false);
2088 return this.ApplyAsync(this.componentAddress, Properties, Preview);
2101 TaskCompletionSource<LegalIdentity> Result =
new TaskCompletionSource<LegalIdentity>();
2103 await this.Apply(Address, Properties, Preview, (Sender, e) =>
2106 Result.TrySetResult(e.Identity);
2108 Result.TrySetException(e.StanzaError ??
new Exception(
"Unable to apply for a legal identity to be registered."));
2110 return Task.CompletedTask;
2114 return await Result.Task;
2119 #region Mark Identity as Ready for Approval
2129 public Task
ReadyForApproval(
string LegalIdentityId, EventHandlerAsync<IqResultEventArgs> Callback,
object State)
2131 return this.ReadyForApproval(this.componentAddress, LegalIdentityId, Callback, State);
2143 public Task
ReadyForApproval(
string Address,
string LegalIdentityId, EventHandlerAsync<IqResultEventArgs> Callback,
object State)
2145 this.AssertAllowed();
2147 StringBuilder Xml =
new StringBuilder();
2149 Xml.Append(
"<readyForApproval xmlns=\"");
2150 Xml.Append(NamespaceLegalIdentitiesCurrent);
2151 Xml.Append(
"\" id=\"");
2152 Xml.Append(
XML.
Encode(LegalIdentityId));
2155 return this.client.SendIqSet(Address, Xml.ToString(), Callback, State);
2166 return this.ReadyForApprovalAsync(this.componentAddress, LegalIdentityId);
2178 TaskCompletionSource<bool> Result =
new TaskCompletionSource<bool>();
2180 await this.ReadyForApproval(Address, LegalIdentityId, (Sender, e) =>
2183 Result.TrySetResult(
true);
2185 Result.TrySetException(e.StanzaError ??
new Exception(
"Unable to flag identity as ready for approval."));
2187 return Task.CompletedTask;
2196 #region Identity Review message
2198 private async Task IdentityReviewEventHandler(
object Sender,
MessageEventArgs e)
2202 ParseValidationDetails(e.
Content, e2);
2207 await this.AddIdentityReviewAttachment(e2);
2210 await this.IdentityReview.Raise(
this, e2);
2236 foreach (XmlNode N
in Content.ChildNodes)
2238 if (!(N is XmlElement E))
2241 switch (E.LocalName)
2243 case "invalidClaim":
2251 InvalidClaims.Add(
new InvalidClaim(Claim, Message, Language, Code, Service));
2254 case "invalidPhoto":
2262 InvalidPhotos.Add(
new InvalidPhoto(FileName, Message, Language, Code, Service));
2274 foreach (XmlNode N2
in E.ChildNodes)
2276 if (!(N2 is XmlElement E2))
2279 if (E2.LocalName ==
"tag")
2286 TagValueParsed = TagValue;
2289 Tags.
Add(
new KeyValuePair<string, object>(TagName, TagValueParsed));
2294 ValidationErrors.Add(
new ValidationError(Type, Message, Language, Code, Service,
2295 Tags?.ToArray() ?? Array.Empty<KeyValuePair<string, object>>()));
2298 case "validatedClaim":
2303 ValidClaims.Add(
new ValidClaim(Claim, Service));
2306 case "validatedPhoto":
2311 ValidPhotos.Add(
new ValidPhoto(FileName, Service));
2314 case "potentialClaim":
2323 case "unvalidatedClaim":
2327 UnvalidatedClaims.Add(Claim);
2330 case "unvalidatedPhoto":
2334 UnvalidatedPhotos.Add(FileName);
2339 e.InvalidClaims = InvalidClaims?.ToArray();
2340 e.InvalidPhotos = InvalidPhotos?.ToArray();
2341 e.ValidationErrors = ValidationErrors?.ToArray();
2342 e.ValidClaims = ValidClaims?.ToArray();
2343 e.ValidPhotos = ValidPhotos?.ToArray();
2344 e.PotentialClaims = PotentialClaims?.ToArray();
2345 e.UnvalidatedClaims = UnvalidatedClaims?.ToArray();
2346 e.UnvalidatedPhotos = UnvalidatedPhotos?.ToArray();
2356 string Xml = e.
Content.OuterXml;
2357 byte[] Data = Encoding.UTF8.GetBytes(Xml.ToString());
2358 string FileName =
"ApplicationReview.xml";
2359 string ContentType = XmlCodec.DefaultContentType +
"; charset=utf-8";
2361 return await this.UploadLegalIdAttachmentAsync(e.
LegalId, FileName, Data, ContentType);
2366 #region Client Message
2368 private async Task ClientMessageEventHandler(
object Sender,
MessageEventArgs e)
2374 ParseValidationDetails(e.
Content, e2);
2376 await this.ClientMessage.Raise(
this, e2);
2386 #region Validate Legal Identity
2396 return this.Validate(Identity,
true,
true, Callback, State);
2406 public Task
Validate(
LegalIdentity Identity,
bool ValidateState, EventHandlerAsync<IdentityValidationEventArgs> Callback,
object State)
2408 return this.Validate(Identity, ValidateState,
true, Callback, State);
2420 EventHandlerAsync<IdentityValidationEventArgs> Callback,
object State)
2422 if (Identity is
null)
2424 await this.ReturnStatus(
IdentityStatus.IdentityUndefined, Callback, State);
2430 await this.ReturnStatus(
IdentityStatus.NotApproved, Callback, State,
2431 new KeyValuePair<string, object>(
"State", Identity.
State));
2435 DateTime UtcNow = DateTime.UtcNow;
2437 if (UtcNow < Identity.
From.ToUniversalTime())
2439 await this.ReturnStatus(
IdentityStatus.NotValidYet, Callback, State,
2440 new KeyValuePair<string, object>(
"From", Identity.
From));
2444 if (UtcNow > Identity.
To.ToUniversalTime())
2446 await this.ReturnStatus(
IdentityStatus.NotValidAnymore, Callback, State,
2447 new KeyValuePair<string, object>(
"To", Identity.
To));
2451 if (
string.IsNullOrEmpty(Identity.
Provider))
2453 await this.ReturnStatus(
IdentityStatus.NoTrustProvider, Callback, State);
2460 await this.ReturnStatus(
IdentityStatus.NoClientPublicKey, Callback, State);
2466 await this.ReturnStatus(
IdentityStatus.NoClientSignature, Callback, State);
2470 StringBuilder Xml =
new StringBuilder();
2471 Identity.
Serialize(Xml,
false,
false,
false,
false,
false,
false,
false);
2472 byte[] Data = Encoding.UTF8.GetBytes(Xml.ToString());
2474 bool? b = this.ValidateSignature(Identity, Data, Identity.
ClientSignature);
2479 await this.ReturnStatus(
IdentityStatus.ClientSignatureInvalid, Callback, State,
2480 new KeyValuePair<string, object>(
"DataBase64", Convert.ToBase64String(Data)),
2481 new KeyValuePair<string, object>(
"SignatureBase64", Convert.ToBase64String(Identity.
ClientSignature)),
2482 new KeyValuePair<string, object>(
"ClientKeyName", Identity.
ClientKeyName),
2483 new KeyValuePair<string, object>(
"ClientPubKeyBase64", Convert.ToBase64String(Identity.
ClientPubKey)));
2489 await this.ReturnStatus(
IdentityStatus.ClientKeyNotRecognized, Callback, State,
2490 new KeyValuePair<string, object>(
"KeyName", Identity.
ClientKeyName));
2495 ValidateAttachments && !(Identity.
Attachments is
null))
2501 await this.ReturnStatus(
IdentityStatus.AttachmentLacksUrl, Callback, State,
2502 new KeyValuePair<string, object>(
"AttachmentId",
Attachment.
Id));
2508 KeyValuePair<string, TemporaryFile> P = await this.GetAttachmentAsync(
Attachment.
Url,
SignWith.LatestApprovedIdOrCurrentKeys, 30000);
2513 await this.ReturnStatus(
IdentityStatus.AttachmentInconsistency, Callback, State,
2514 new KeyValuePair<string, object>(
"AttachmentId",
Attachment.
Id),
2515 new KeyValuePair<string, object>(
"AttachmentUrl",
Attachment.
Url),
2517 new KeyValuePair<string, object>(
"ContentType", P.Key));
2528 await this.ReturnStatus(
IdentityStatus.AttachmentSignatureInvalid, Callback, State,
2529 new KeyValuePair<string, object>(
"AttachmentId",
Attachment.
Id),
2530 new KeyValuePair<string, object>(
"AttachmentUrl",
Attachment.
Url),
2531 new KeyValuePair<string, object>(
"AttachmentSignatureBase64", Convert.ToBase64String(
Attachment.
Signature)));
2537 await this.ReturnStatus(
IdentityStatus.ClientKeyNotRecognized, Callback, State,
2538 new KeyValuePair<string, object>(
"AttachmentId",
Attachment.
Id),
2539 new KeyValuePair<string, object>(
"AttachmentUrl",
Attachment.
Url),
2540 new KeyValuePair<string, object>(
"KeyName", Identity.
ClientKeyName));
2544 catch (Exception ex)
2546 this.client.Error(
"Attachment " +
Attachment.
Url +
"unavailable: " + ex.Message);
2547 await this.ReturnStatus(
IdentityStatus.AttachmentUnavailable, Callback, State,
2548 new KeyValuePair<string, object>(
"AttachmentId",
Attachment.
Id),
2549 new KeyValuePair<string, object>(
"AttachmentUrl",
Attachment.
Url),
2550 new KeyValuePair<string, object>(
"Error", ex.Message));
2558 await this.ReturnStatus(
IdentityStatus.NoProviderSignature, Callback, State);
2563 Identity.
Serialize(Xml,
false,
true,
true,
true,
true,
false,
false);
2564 Data = Encoding.UTF8.GetBytes(Xml.ToString());
2566 bool HasOldPublicKey = this.publicKeys.TryGetRecord(Identity.
Provider,
2569 await this.GetServerPublicKey(Identity.
Provider, Identity.
Updated, async (Sender, e) =>
2571 if (e.
Ok && !(e.Key is
null))
2573 bool Valid = e.Key.Verify(Data, Identity.ServerSignature);
2577 await this.ReturnStatus(IdentityStatus.Valid, Callback, State);
2581 if (!HasOldPublicKey)
2583 await this.ReturnStatus(
IdentityStatus.ProviderSignatureInvalid, Callback, State,
2584 new KeyValuePair<string, object>(
"Provider", Identity.
Provider),
2585 new KeyValuePair<string, object>(
"LocalName", e.Key.LocalName),
2586 new KeyValuePair<string, object>(
"Namespace", e.Key.Namespace),
2587 new KeyValuePair<string, object>(
"PublicKeyBase64", e.Key.PublicKeyBase64),
2588 new KeyValuePair<string, object>(
"DataBase64", Convert.ToBase64String(Data)),
2589 new KeyValuePair<string, object>(
"SignatureBase64", Convert.ToBase64String(Identity.
ServerSignature)));
2593 this.publicKeys.Remove(Identity.
Provider);
2598 if (e2.Ok && !(e2.Key is null))
2600 if (e.Key.Equals(e2.Key))
2602 return this.ReturnStatus(IdentityStatus.ProviderSignatureInvalid, Callback, State,
2603 new KeyValuePair<string, object>(
"Provider", Identity.Provider),
2604 new KeyValuePair<string, object>(
"LocalName", e.Key.LocalName),
2605 new KeyValuePair<string, object>(
"Namespace", e.Key.Namespace),
2606 new KeyValuePair<string, object>(
"PublicKeyBase64", e.Key.PublicKeyBase64),
2607 new KeyValuePair<string, object>(
"DataBase64", Convert.ToBase64String(Data)),
2608 new KeyValuePair<string, object>(
"SignatureBase64", Convert.ToBase64String(Identity.ServerSignature)));
2611 Valid = e2.Key.Verify(Data, Identity.ServerSignature);
2614 return this.ReturnStatus(IdentityStatus.Valid, Callback, State);
2617 return this.ReturnStatus(IdentityStatus.ProviderSignatureInvalid, Callback, State,
2618 new KeyValuePair<string, object>(
"Provider", Identity.Provider),
2619 new KeyValuePair<string, object>(
"LocalName", e2.Key.LocalName),
2620 new KeyValuePair<string, object>(
"Namespace", e2.Key.Namespace),
2621 new KeyValuePair<string, object>(
"PublicKeyBase64", e.Key.PublicKeyBase64),
2622 new KeyValuePair<string, object>(
"DataBase64", Convert.ToBase64String(Data)),
2623 new KeyValuePair<string, object>(
"SignatureBase64", Convert.ToBase64String(Identity.ServerSignature)));
2628 return this.ReturnStatus(IdentityStatus.NoProviderPublicKey, Callback, State,
2629 new KeyValuePair<string, object>(
"Provider", Identity.Provider));
2636 await this.ReturnStatus(
IdentityStatus.NoResponse, Callback, State,
2637 new KeyValuePair<string, object>(
"Provider", Identity.
Provider));
2641 await this.ReturnStatus(
IdentityStatus.NoProviderPublicKey, Callback, State,
2642 new KeyValuePair<string, object>(
"Provider", Identity.
Provider));
2667 Identity.
Namespace.Replace(
":iot:leg:id:",
":iot:e2e:").Replace(
"urn:ieee:",
"urn:nf:"),
2696 Identity.
Namespace.Replace(
":iot:leg:id:",
":iot:e2e:").Replace(
"urn:ieee:",
"urn:nf:"),
2706 private async Task ReturnStatus(
IdentityStatus Status, EventHandlerAsync<IdentityValidationEventArgs> Callback,
object State,
2707 params KeyValuePair<string, object>[] Tags)
2719 return this.ValidateAsync(Identity,
true,
true);
2730 return this.ValidateAsync(Identity, ValidateState,
true);
2741 bool ValidateState,
bool ValidateAttachments)
2743 TaskCompletionSource<IdentityValidationEventArgs> Result =
new TaskCompletionSource<IdentityValidationEventArgs>();
2745 await this.Validate(Identity, ValidateState, ValidateAttachments, (Sender, e) =>
2747 Result.TrySetResult(e);
2748 return Task.CompletedTask;
2751 return await Result.Task;
2756 #region Legal Identity update event
2758 private bool IsFromTrustProvider(
string Id,
string From)
2760 int i = Id.IndexOf(
'@');
2766 i = From.IndexOf(
'@');
2770 return (
string.Compare(Id, From,
true) == 0 ||
2771 From.EndsWith(
"." + Id, StringComparison.CurrentCultureIgnoreCase));
2774 private async Task IdentityMessageHandler(
object Sender,
MessageEventArgs e)
2778 if (!this.IsFromTrustProvider(Identity.
Id, e.
From))
2780 this.client.Warning(
"Incoming identity message discarded: " + Identity.
Id +
" not from " + e.
From +
".");
2786 this.client.Warning(
"Incoming identity message discarded: Sender " + e.
FromBareJID +
" not equal to Trust Provider " + Identity.
Provider +
".");
2790 await this.Validate(Identity,
false, async (sender2, e2) =>
2794 this.client.Warning(
"Invalid legal identity received and discarded. Validation status: " + e2.Status.ToString());
2796 Log.Warning(
"Invalid legal identity received and discarded.", this.client.BareJID, e.From,
2797 new KeyValuePair<string, object>(
"Status", e2.Status));
2802 await
this.UpdateSettings(Identity);
2810 return this.UpdateSettings(Identity, Identity?.ClientPubKey);
2821 return this.HasPrivateKey(Identity.
Id);
2836 using LoadedKey Key = await this.TryGetLegalIdentityEndpointAsync(State,
true,
false);
2838 return !(Key.Endpoint is
null);
2847 return this.GetLatestApprovedLegalId(
null);
2857 string PublicKeyBase64 = PublicKey is
null ? string.Empty : Convert.ToBase64String(PublicKey);
2863 using LoadedKey Key = await this.TryGetLegalIdentityEndpointAsync(State,
true,
false);
2865 if (Key.Endpoint is
null || State.
PublicKey is
null)
2868 if (!(PublicKey is
null) && Convert.ToBase64String(State.
PublicKey) != PublicKeyBase64)
2877 private async Task<LoadedKey> GetLatestApprovedKey(
bool ExceptionIfNone)
2879 bool HaveStates =
false;
2887 LoadedKey Key = await this.TryGetLegalIdentityEndpointAsync(State,
true,
false);
2888 if (!(Key.Endpoint is
null))
2894 if (ExceptionIfNone)
2898 throw new Exception(
"Private keys are not available on this device (" + this.client.BareJID +
2899 "). Were they created on another device?");
2902 throw new Exception(
"No approved legal identity available on this device (" + this.client.BareJID +
").");
2905 return new LoadedKey(
null,
false, DateTime.MinValue);
2908 private async Task<LegalIdentityState> FindPreviewStateAsync(
byte[] PublicKey,
string LegalId)
2910 if (PublicKey is
null)
2924 private async Task UpdateSettings(
LegalIdentity Identity,
byte[] PublicKey)
2928 if (!
string.IsNullOrEmpty(Identity.
Id))
2932 if (
string.IsNullOrEmpty(StateObj.
ObjectId))
2938 if (StateObj2 is
null)
2940 StateObj2 = await this.FindPreviewStateAsync(PublicKey, Identity.
Id);
2941 if (StateObj2 is
null)
2942 StateObj.BareJid = this.client.BareJID;
2945 if (!
string.IsNullOrEmpty(StateObj2.
LegalId))
2948 StateObj2.LegalId = Identity.
Id;
2950 StateObj = StateObj2;
2956 StateObj = StateObj2;
2960 DateTime Timestamp = Identity.Updated > Identity.Created ? Identity.Updated : Identity.
Created;
2963 (StateObj.
PublicKey is
null && !(PublicKey is
null)) ||
2965 (
string.IsNullOrEmpty(StateObj.
KeyName) && !(PublicKey is
null)) ||
2968 StateObj.State = Identity.
State;
2969 StateObj.Timestamp = Timestamp;
2971 if (PublicKey is
null)
2973 switch (Identity.
State)
2978 StateObj.PublicKey =
null;
2984 if (await this.LoadKeys(
false))
2986 IE2eEndpoint Endpoint = this.LocalEndpoint.FindLocalEndpoint(PublicKey);
2988 if (!(Endpoint is
null))
2989 await this.SetLegalIdentityKeySnapshotAsync(StateObj, Endpoint);
2991 StateObj.PublicKey = Clone(PublicKey);
2994 StateObj.PublicKey = Clone(PublicKey);
2997 if (
string.IsNullOrEmpty(StateObj.
ObjectId))
3009 public event EventHandlerAsync<LegalIdentityEventArgs> IdentityUpdated =
null;
3013 #region Get Legal Identities
3022 return this.GetLegalIdentities(this.componentAddress, Callback, State);
3031 public Task
GetLegalIdentities(
string Address, EventHandlerAsync<LegalIdentitiesEventArgs> Callback,
object State)
3033 return this.client.SendIqGet(Address,
"<getLegalIdentities xmlns=\"" + NamespaceLegalIdentitiesCurrent +
"\"/>",
3034 this.IdentitiesResponse,
new object[] { Callback, State });
3039 object[] P = (
object[])e.
State;
3040 EventHandlerAsync<LegalIdentitiesEventArgs> Callback = (EventHandlerAsync<LegalIdentitiesEventArgs>)P[0];
3044 if (e.
Ok && !((E = e.
FirstElement) is
null) && E.LocalName ==
"identities")
3046 List<LegalIdentity> IdentitiesList =
new List<LegalIdentity>();
3048 foreach (XmlNode N
in E.ChildNodes)
3050 if (N is XmlElement E2 && E2.LocalName ==
"identity")
3053 IdentitiesList.Add(Identity);
3057 await this.UpdateSettings(Identity);
3059 catch (Exception ex)
3066 Identities = IdentitiesList.ToArray();
3081 return this.GetLegalIdentitiesAsync(this.componentAddress);
3091 TaskCompletionSource<LegalIdentity[]> Result =
new TaskCompletionSource<LegalIdentity[]>();
3093 await this.GetLegalIdentities(Address, (Sender, e) =>
3096 Result.TrySetResult(e.Identities);
3098 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get legal identities."));
3100 return Task.CompletedTask;
3104 return await Result.Task;
3109 #region Get Legal Identity
3117 public Task
GetLegalIdentity(
string LegalIdentityId, EventHandlerAsync<LegalIdentityEventArgs> Callback,
object State)
3119 return this.GetLegalIdentity(this.GetTrustProvider(LegalIdentityId), LegalIdentityId, Callback, State);
3129 int i = EntityId.IndexOf(
'@');
3131 return this.componentAddress;
3133 return EntityId[(i + 1)..];
3143 public Task
GetLegalIdentity(
string Address,
string LegalIdentityId, EventHandlerAsync<LegalIdentityEventArgs> Callback,
object State)
3145 return this.client.SendIqGet(Address,
"<getLegalIdentity id=\"" +
XML.
Encode(LegalIdentityId) +
"\" xmlns=\"" +
3146 NamespaceLegalIdentitiesCurrent +
"\"/>", async (Sender, e) =>
3151 if (e.
Ok && !((E = e.
FirstElement) is
null) && E.LocalName ==
"identity")
3167 return this.GetLegalIdentityAsync(this.GetTrustProvider(LegalIdentityId), LegalIdentityId);
3178 TaskCompletionSource<LegalIdentity> Result =
new TaskCompletionSource<LegalIdentity>();
3180 await this.GetLegalIdentity(Address, LegalIdentityId, (Sender, e) =>
3183 Result.TrySetResult(e.Identity);
3185 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get legal identity."));
3187 return Task.CompletedTask;
3191 return await Result.Task;
3196 #region Obsolete Legal Identity
3204 public Task
ObsoleteLegalIdentity(
string LegalIdentityId, EventHandlerAsync<LegalIdentityEventArgs> Callback,
object State)
3206 return this.ObsoleteLegalIdentity(this.GetTrustProvider(LegalIdentityId), LegalIdentityId, Callback, State);
3216 public Task
ObsoleteLegalIdentity(
string Address,
string LegalIdentityId, EventHandlerAsync<LegalIdentityEventArgs> Callback,
object State)
3218 this.AssertAllowed();
3220 return this.client.SendIqSet(Address,
"<obsoleteLegalIdentity id=\"" +
XML.
Encode(LegalIdentityId) +
"\" xmlns=\"" +
3221 NamespaceLegalIdentitiesCurrent +
"\"/>", async (Sender, e) =>
3226 if (e.
Ok && !((E = e.
FirstElement) is
null) && E.LocalName ==
"identity")
3228 Identity = LegalIdentity.Parse(E);
3229 await this.UpdateSettings(Identity);
3245 return this.ObsoleteLegalIdentityAsync(this.GetTrustProvider(LegalIdentityId), LegalIdentityId);
3256 TaskCompletionSource<LegalIdentity> Result =
new TaskCompletionSource<LegalIdentity>();
3258 await this.ObsoleteLegalIdentity(Address, LegalIdentityId, (Sender, e) =>
3261 Result.TrySetResult(e.Identity);
3263 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to obsolete legal identity."));
3265 return Task.CompletedTask;
3269 return await Result.Task;
3274 #region Compromised Legal Identity
3284 return this.CompromisedLegalIdentity(this.GetTrustProvider(LegalIdentityId), LegalIdentityId, Callback, State);
3294 public Task
CompromisedLegalIdentity(
string Address,
string LegalIdentityId, EventHandlerAsync<LegalIdentityEventArgs> Callback,
object State)
3296 this.AssertAllowed();
3298 return this.client.SendIqSet(Address,
"<compromisedLegalIdentity id=\"" +
XML.
Encode(LegalIdentityId) +
"\" xmlns=\"" +
3299 NamespaceLegalIdentitiesCurrent +
"\"/>", async (Sender, e) =>
3304 if (e.
Ok && !((E = e.
FirstElement) is
null) && E.LocalName ==
"identity")
3306 Identity = LegalIdentity.Parse(E);
3307 await this.UpdateSettings(Identity);
3323 return this.CompromisedLegalIdentityAsync(this.GetTrustProvider(LegalIdentityId), LegalIdentityId);
3334 TaskCompletionSource<LegalIdentity> Result =
new TaskCompletionSource<LegalIdentity>();
3336 await this.CompromisedLegalIdentity(Address, LegalIdentityId, (Sender, e) =>
3339 Result.TrySetResult(e.Identity);
3341 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to compromise legal identity."));
3343 return Task.CompletedTask;
3347 return await Result.Task;
3363 return this.Sign(this.componentAddress, Data,
SignWith, Callback, State);
3374 public async Task
Sign(
string Address,
byte[] Data,
SignWith SignWith, EventHandlerAsync<SignatureEventArgs> Callback,
object State)
3376 this.AssertAllowed();
3379 LoadedKey KeyInfo =
SignWith switch
3381 SignWith.CurrentKeys =>
new LoadedKey(
null,
false, DateTime.MinValue),
3382 SignWith.LatestApprovedId => await this.GetLatestApprovedKey(
true),
3383 _ => await this.GetLatestApprovedKey(
false),
3391 await this.GetMatchingLocalKey(Address, async (Sender, e) =>
3420 return this.SignAsync(this.componentAddress, Data,
SignWith);
3432 TaskCompletionSource<byte[]> Result =
new TaskCompletionSource<byte[]>();
3434 await this.Sign(Address, Data,
SignWith, (Sender, e) =>
3437 Result.TrySetResult(e.Signature);
3439 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to sign data."));
3441 return Task.CompletedTask;
3445 return await Result.Task;
3457 return this.Sign(this.componentAddress, Data,
SignWith, Callback, State);
3468 public async Task
Sign(
string Address, Stream Data,
SignWith SignWith, EventHandlerAsync<SignatureEventArgs> Callback,
object State)
3470 this.AssertAllowed();
3472 LoadedKey KeyInfo =
SignWith == SignWith.CurrentKeys ?
3473 new LoadedKey(
null,
false, DateTime.MinValue)
3474 : await this.GetLatestApprovedKey(
true);
3482 await this.GetMatchingLocalKey(Address, async (Sender, e) =>
3511 return this.SignAsync(this.componentAddress, Data,
SignWith);
3523 TaskCompletionSource<byte[]> Result =
new TaskCompletionSource<byte[]>();
3525 await this.Sign(Address, Data,
SignWith, (Sender, e) =>
3528 Result.TrySetResult(e.Signature);
3530 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to sign data."));
3532 return Task.CompletedTask;
3536 return await Result.Task;
3541 #region Validating Signatures
3553 return this.ValidateSignature(this.GetTrustProvider(LegalId), LegalId, Data,
Signature, Callback, State);
3566 EventHandlerAsync<LegalIdentityEventArgs> Callback,
object State)
3568 EventHandlerAsync<ValidateSignatureEventArgs> h = ValidateLocalSignature;
3572 await h.Raise(
this, e,
false);
3574 if (e.
Valid.HasValue)
3576 if (!(Callback is
null))
3578 XmlDocument Doc =
new XmlDocument();
3579 XmlElement Empty = Doc.CreateElement(
"Local");
3586 await Callback.Raise(
this, e2);
3593 StringBuilder Xml =
new StringBuilder();
3595 Xml.Append(
"<validateSignature data=\"");
3596 Xml.Append(Convert.ToBase64String(Data));
3598 if (!
string.IsNullOrEmpty(LegalId))
3600 Xml.Append(
"\" id=\"");
3604 Xml.Append(
"\" s=\"");
3605 Xml.Append(Convert.ToBase64String(
Signature));
3607 Xml.Append(
"\" xmlns=\"");
3608 Xml.Append(NamespaceLegalIdentitiesCurrent);
3611 await this.client.SendIqGet(Address, Xml.ToString(), async (Sender, e) =>
3616 if (e.
Ok && !((E = e.
FirstElement) is
null) && E.LocalName ==
"identity")
3629 public static event EventHandlerAsync<ValidateSignatureEventArgs> ValidateLocalSignature =
null;
3640 return this.ValidateSignatureAsync(this.GetTrustProvider(LegalId), LegalId, Data,
Signature);
3653 TaskCompletionSource<LegalIdentity> Result =
new TaskCompletionSource<LegalIdentity>();
3655 await this.ValidateSignature(Address, LegalId, Data,
Signature, (Sender, e) =>
3658 Result.TrySetResult(e.Identity);
3660 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to verify signature."));
3662 return Task.CompletedTask;
3666 return await Result.Task;
3678 return this.ValidateSignatureAsyncEx(this.GetTrustProvider(LegalId), LegalId, Data,
Signature);
3691 TaskCompletionSource<KeyValuePair<LegalIdentity, Exception>> Result =
new TaskCompletionSource<KeyValuePair<LegalIdentity, Exception>>();
3693 await this.ValidateSignature(Address, LegalId, Data,
Signature, (Sender, e) =>
3696 Result.TrySetResult(
new KeyValuePair<LegalIdentity, Exception>(e.Identity,
null));
3698 Result.TrySetResult(
new KeyValuePair<LegalIdentity, Exception>(
null, e.
StanzaError ??
new Exception(
"Unable to verify signature.")));
3700 return Task.CompletedTask;
3704 return await Result.Task;
3718 public Task
GetTrustChain(EventHandlerAsync<TrustChainEventArgs> Callback,
object State)
3720 return this.GetTrustChain(this.client.Domain, Callback, State);
3731 public async Task
GetTrustChain(
string Domain, EventHandlerAsync<TrustChainEventArgs> Callback,
object State)
3733 StringBuilder Xml =
new StringBuilder();
3735 Xml.Append(
"<getTrustChain xmlns=\"");
3736 Xml.Append(NamespaceLegalIdentitiesCurrent);
3739 await this.client.SendIqGet(Domain, Xml.ToString(), async (Sender, e) =>
3744 if (e.
Ok && !((E = e.
FirstElement) is
null) && E.LocalName ==
"trustChain")
3746 Brokers = new ChunkedList<string>();
3748 foreach (XmlNode N in E.ChildNodes)
3750 if (N is XmlElement E2 &&
3751 E2.LocalName ==
"broker" &&
3752 IsNamespaceLegalIdentity(E2.NamespaceURI))
3754 Brokers.Add(XML.Attribute(E2,
"domain"));
3773 return this.GetTrustChainAsync(this.client.Domain);
3785 TaskCompletionSource<string[]> Result =
new TaskCompletionSource<string[]>();
3787 await this.GetTrustChain(Domain, (Sender, e) =>
3790 Result.TrySetResult(e.Domains);
3792 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get the trust chain of domains from " + Domain +
"."));
3794 return Task.CompletedTask;
3798 return await Result.Task;
3803 #region Create Contract
3826 Duration? ArchiveRequired,
Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore,
bool CanActAsTemplate,
3827 EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
3829 return this.CreateContract(this.componentAddress, ForMachines, ForHumans, Roles, Parts, Parameters, Visibility, PartsMode,
3830 Duration, ArchiveRequired, ArchiveOptional, SignAfter, SignBefore, CanActAsTemplate, Callback, State);
3855 Duration? ArchiveRequired,
Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore,
bool CanActAsTemplate,
3856 EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
3858 return this.CreateContract(Address, ForMachines, ForHumans, Roles, Parts, Parameters,
3859 Visibility, PartsMode,
Duration, ArchiveRequired, ArchiveOptional, SignAfter,
3860 SignBefore, CanActAsTemplate,
null, Callback, State);
3886 Duration? ArchiveRequired,
Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore,
bool CanActAsTemplate,
3889 StringBuilder Xml =
new StringBuilder();
3891 Xml.Append(
"<createContract xmlns=\"");
3892 Xml.Append(NamespaceSmartContractsCurrent);
3897 Namespace = NamespaceSmartContractsCurrent,
3898 ForMachines = ForMachines,
3899 ForHumans = ForHumans,
3902 Parameters = Parameters,
3903 Visibility = Visibility,
3904 PartsMode = PartsMode,
3906 ArchiveRequired = ArchiveRequired,
3907 ArchiveOptional = ArchiveOptional,
3908 SignAfter = SignAfter,
3909 SignBefore = SignBefore,
3910 CanActAsTemplate = CanActAsTemplate
3913 byte[] Nonce = Guid.NewGuid().ToByteArray();
3914 string NonceStr = Convert.ToBase64String(Nonce);
3928 Xml.Append(
"<transient>");
3940 Xml.Append(
"</transient>");
3943 Xml.Append(
"</createContract>");
3945 await this.client.SendIqSet(Address, Xml.ToString(),
this.ContractResponse,
new object[] { Callback, State, Contract.HasEncryptedParameters, Algorithm?.Algorithm, Algorithm?.Key });
3950 object[] P = (
object[])e.
State;
3951 EventHandlerAsync<SmartContractEventArgs> Callback = (EventHandlerAsync<SmartContractEventArgs>)P[0];
3955 if (e.
Ok && !((E = e.
FirstElement) is
null) && E.LocalName ==
"contract")
3963 string CreatorJid = this.client.BareJID;
3965 if (P.Length >= 5 &&
3966 P[2] is
bool HasEncryptedParameters &&
3967 HasEncryptedParameters &&
3972 CreatorJid, Key, Algorithm,
false);
3976 Tuple<SymmetricCipherAlgorithms, string, byte[]> T = await this.TryLoadContractSharedSecret(
Contract.
ContractId);
3978 if (HasEncryptedParameters = !(T is
null))
3980 Algorithm = T.Item1;
3981 CreatorJid = T.Item2;
3986 Algorithm = this.preferredEncryptionAlgorithm;
3991 if (HasEncryptedParameters)
4027 Duration? ArchiveRequired,
Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore,
bool CanActAsTemplate)
4029 return this.CreateContractAsync(this.componentAddress, ForMachines, ForHumans, Roles, Parts, Parameters, Visibility,
4030 PartsMode,
Duration, ArchiveRequired, ArchiveOptional, SignAfter, SignBefore, CanActAsTemplate);
4054 Duration? ArchiveRequired,
Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore,
bool CanActAsTemplate)
4056 TaskCompletionSource<Contract> Result =
new TaskCompletionSource<Contract>();
4058 await this.CreateContract(Address, ForMachines, ForHumans, Roles, Parts, Parameters, Visibility, PartsMode,
Duration,
4059 ArchiveRequired, ArchiveOptional, SignAfter, SignBefore, CanActAsTemplate, (Sender, e) =>
4062 Result.TrySetResult(e.Contract);
4064 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to create the contract."));
4066 return Task.CompletedTask;
4070 return await Result.Task;
4075 #region Create Contract From Template
4096 DateTime? SignBefore,
bool CanActAsTemplate, EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
4098 return this.CreateContract(this.componentAddress, TemplateId, Parts, Parameters, Visibility, PartsMode,
Duration,
4099 ArchiveRequired, ArchiveOptional, SignAfter, SignBefore, CanActAsTemplate,
null, Callback, State);
4122 DateTime? SignBefore,
bool CanActAsTemplate, EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
4124 return this.CreateContract(Address, TemplateId, Parts, Parameters, Visibility,
4125 PartsMode,
Duration, ArchiveRequired, ArchiveOptional, SignAfter,
4126 SignBefore, CanActAsTemplate,
null, Callback, State);
4152 EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
4154 StringBuilder Xml =
new StringBuilder();
4155 uint i, c = (uint)(Parameters?.Length ?? 0);
4156 bool HasEncryptedParameters =
false;
4158 for (i = 0; i < c; i++)
4164 HasEncryptedParameters =
true;
4169 byte[] Nonce = Guid.NewGuid().ToByteArray();
4170 string NonceStr = Convert.ToBase64String(Nonce);
4173 if (HasEncryptedParameters)
4177 for (i = 0; i < c; i++)
4186 Xml.Append(
"<createContract xmlns=\"");
4187 Xml.Append(NamespaceSmartContractsCurrent);
4188 Xml.Append(
"\"><template archiveOpt=\"");
4189 Xml.Append(ArchiveOptional.
ToString());
4190 Xml.Append(
"\" archiveReq=\"");
4191 Xml.Append(ArchiveRequired.
ToString());
4192 Xml.Append(
"\" canActAsTemplate=\"");
4194 Xml.Append(
"\" duration=\"");
4196 Xml.Append(
"\" id=\"");
4198 Xml.Append(
"\" nonce=\"");
4199 Xml.Append(NonceStr);
4202 if (SignAfter.HasValue && SignAfter > DateTime.MinValue)
4204 Xml.Append(
" signAfter=\"");
4205 Xml.Append(
XML.
Encode(SignAfter.Value));
4209 if (SignBefore.HasValue && SignBefore < DateTime.MaxValue)
4211 Xml.Append(
" signBefore=\"");
4212 Xml.Append(
XML.
Encode(SignBefore.Value));
4216 Xml.Append(
" visibility=\"");
4217 Xml.Append(Visibility.ToString());
4218 Xml.Append(
"\"><parts>");
4223 Xml.Append(
"<open/>");
4227 Xml.Append(
"<templateOnly/>");
4231 if (!(Parts is
null))
4235 Xml.Append(
"<part legalId=\"");
4237 Xml.Append(
"\" role=\"");
4245 Xml.Append(
"</parts>");
4247 LinkedList<Parameter> TransientParameters =
null;
4249 if (!(Parameters is
null) && Parameters.Length > 0)
4251 Xml.Append(
"<parameters>");
4257 Parameter.ProtectedValue ??= Guid.NewGuid().ToByteArray();
4259 TransientParameters ??=
new LinkedList<Parameter>();
4266 Xml.Append(
"</parameters>");
4269 Xml.Append(
"</template>");
4271 if (!(TransientParameters is
null))
4273 Xml.Append(
"<transient>");
4282 Xml.Append(
"</transient>");
4285 Xml.Append(
"</createContract>");
4287 await this.client.SendIqSet(Address, Xml.ToString(),
this.ContractResponse,
new object[] { Callback, State, HasEncryptedParameters, Algorithm?.Algorithm, Algorithm?.Key });
4308 DateTime? SignBefore,
bool CanActAsTemplate)
4310 return this.CreateContractAsync(this.componentAddress, TemplateId, Parts, Parameters, Visibility,
4311 PartsMode,
Duration, ArchiveRequired, ArchiveOptional, SignAfter, SignBefore, CanActAsTemplate);
4333 DateTime? SignAfter, DateTime? SignBefore,
bool CanActAsTemplate)
4335 TaskCompletionSource<Contract> Result =
new TaskCompletionSource<Contract>();
4337 await this.CreateContract(Address, TemplateId, Parts, Parameters, Visibility, PartsMode,
Duration,
4338 ArchiveRequired, ArchiveOptional, SignAfter, SignBefore, CanActAsTemplate, (Sender, e) =>
4341 Result.TrySetResult(e.Contract);
4343 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to create the contract."));
4345 return Task.CompletedTask;
4349 return await Result.Task;
4354 #region Get Created Contract References
4363 return this.GetCreatedContractReferences(this.componentAddress, 0,
int.MaxValue, Callback, State);
4374 return this.GetCreatedContractReferences(Address, 0,
int.MaxValue, Callback, State);
4386 return this.GetCreatedContractReferences(this.componentAddress, Offset, MaxCount, Callback, State);
4400 throw new ArgumentException(
"Offsets cannot be negative.", nameof(Offset));
4403 throw new ArgumentException(
"Must be postitive.", nameof(MaxCount));
4405 StringBuilder Xml =
new StringBuilder();
4407 Xml.Append(
"<getCreatedContracts references='true' xmlns='");
4408 Xml.Append(NamespaceSmartContractsCurrent);
4412 Xml.Append(
"' offset='");
4413 Xml.Append(Offset.ToString());
4416 if (MaxCount <
int.MaxValue)
4418 Xml.Append(
"' maxCount='");
4419 Xml.Append(MaxCount.ToString());
4424 return this.client.SendIqGet(Address, Xml.ToString(),
this.IdReferencesResponse,
new object[] { Callback, State });
4429 object[] P = (
object[])e.
State;
4430 EventHandlerAsync<IdReferencesEventArgs> Callback = (EventHandlerAsync<IdReferencesEventArgs>)P[0];
4432 List<string> IDs =
new List<string>();
4434 if (e.
Ok && !(E is
null))
4436 foreach (XmlNode N
in E.ChildNodes)
4438 if (N is XmlElement E2 && E2.LocalName ==
"ref")
4458 return this.GetCreatedContractReferencesAsync(this.componentAddress, 0,
int.MaxValue);
4468 return this.GetCreatedContractReferencesAsync(Address, 0,
int.MaxValue);
4479 return this.GetCreatedContractReferencesAsync(this.componentAddress, Offset, MaxCount);
4491 TaskCompletionSource<string[]> Result =
new TaskCompletionSource<string[]>();
4493 await this.GetCreatedContractReferences(Address, Offset, MaxCount, (Sender, e) =>
4496 Result.TrySetResult(e.References);
4498 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get created contract references."));
4500 return Task.CompletedTask;
4504 return await Result.Task;
4509 #region Get Created Contracts
4518 return this.GetCreatedContracts(this.componentAddress, 0,
int.MaxValue, Callback, State);
4529 return this.GetCreatedContracts(Address, 0,
int.MaxValue, Callback, State);
4539 public Task
GetCreatedContracts(
int Offset,
int MaxCount, EventHandlerAsync<ContractsEventArgs> Callback,
object State)
4541 return this.GetCreatedContracts(this.componentAddress, Offset, MaxCount, Callback, State);
4552 public Task
GetCreatedContracts(
string Address,
int Offset,
int MaxCount, EventHandlerAsync<ContractsEventArgs> Callback,
object State)
4555 throw new ArgumentException(
"Offsets cannot be negative.", nameof(Offset));
4558 throw new ArgumentException(
"Must be postitive.", nameof(MaxCount));
4560 StringBuilder Xml =
new StringBuilder();
4562 Xml.Append(
"<getCreatedContracts references='false' xmlns='");
4563 Xml.Append(NamespaceSmartContractsCurrent);
4567 Xml.Append(
"' offset='");
4568 Xml.Append(Offset.ToString());
4571 if (MaxCount <
int.MaxValue)
4573 Xml.Append(
"' maxCount='");
4574 Xml.Append(MaxCount.ToString());
4579 return this.client.SendIqGet(Address, Xml.ToString(),
this.ContractsResponse,
new object[] { Callback, State });
4584 object[] P = (
object[])e.
State;
4585 EventHandlerAsync<ContractsEventArgs> Callback = (EventHandlerAsync<ContractsEventArgs>)P[0];
4587 List<Contract> Contracts =
new List<Contract>();
4588 List<string> References =
new List<string>();
4590 if (e.
Ok && !(E is
null))
4592 foreach (XmlNode N
in E.ChildNodes)
4594 if (N is XmlElement E2)
4596 switch (E2.LocalName)
4607 References.Add(ContractId);
4617 await Callback.Raise(
this,
new ContractsEventArgs(e, Contracts.ToArray(), References.ToArray()));
4626 return this.GetCreatedContractsAsync(this.componentAddress, 0,
int.MaxValue);
4636 return this.GetCreatedContractsAsync(Address, 0,
int.MaxValue);
4647 return this.GetCreatedContractsAsync(this.componentAddress, Offset, MaxCount);
4659 TaskCompletionSource<ContractsEventArgs> Result =
new TaskCompletionSource<ContractsEventArgs>();
4661 await this.GetCreatedContracts(Address, Offset, MaxCount, (Sender, e) =>
4663 Result.TrySetResult(e);
4664 return Task.CompletedTask;
4668 return await Result.Task;
4673 #region Sign Contract
4702 EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
4706 Tuple<SymmetricCipherAlgorithms, string, byte[]> T = await this.TryLoadContractSharedSecret(
Contract.
ContractId);
4716 StringBuilder Xml =
new StringBuilder();
4718 byte[] Data = Encoding.UTF8.GetBytes(Xml.ToString());
4720 await this.Sign(Address, Data,
SignWith.LatestApprovedId, async (Sender, e) =>
4725 Xml.Append(
"<signContract xmlns='");
4726 Xml.Append(NamespaceSmartContractsCurrent);
4727 Xml.Append(
"' id='");
4728 Xml.Append(XML.Encode(Contract.ContractId));
4729 Xml.Append(
"' role='");
4730 Xml.Append(XML.Encode(Role));
4733 Xml.Append(
"' transferable='true");
4735 Xml.Append(
"' s='");
4736 Xml.Append(Convert.ToBase64String(e.Signature));
4739 await this.client.SendIqSet(Address, Xml.ToString(), this.ContractResponse, new object[] { Callback, State });
4772 TaskCompletionSource<Contract> Result =
new TaskCompletionSource<Contract>();
4774 await this.SignContract(Address,
Contract,
Role, Transferable, (Sender, e) =>
4777 Result.TrySetResult(e.Contract);
4779 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to sign the contract."));
4781 return Task.CompletedTask;
4785 return await Result.Task;
4790 #region Get Signed Contract References
4799 return this.GetSignedContractReferences(this.componentAddress, 0,
int.MaxValue, Callback, State);
4810 return this.GetSignedContractReferences(Address, 0,
int.MaxValue, Callback, State);
4824 throw new ArgumentException(
"Offsets cannot be negative.", nameof(Offset));
4827 throw new ArgumentException(
"Must be postitive.", nameof(MaxCount));
4829 StringBuilder Xml =
new StringBuilder();
4831 Xml.Append(
"<getSignedContracts references='true' xmlns='");
4832 Xml.Append(NamespaceSmartContractsCurrent);
4836 Xml.Append(
"' offset='");
4837 Xml.Append(Offset.ToString());
4840 if (MaxCount <
int.MaxValue)
4842 Xml.Append(
"' maxCount='");
4843 Xml.Append(MaxCount.ToString());
4848 return this.client.SendIqGet(Address, Xml.ToString(),
this.IdReferencesResponse,
new object[] { Callback, State });
4857 return this.GetSignedContractReferencesAsync(this.componentAddress, 0,
int.MaxValue);
4868 return this.GetSignedContractReferencesAsync(this.componentAddress, Offset, MaxCount);
4880 TaskCompletionSource<string[]> Result =
new TaskCompletionSource<string[]>();
4882 await this.GetSignedContractReferences(Address, Offset, MaxCount, (Sender, e) =>
4885 Result.TrySetResult(e.References);
4887 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get signed contract references."));
4889 return Task.CompletedTask;
4893 return await Result.Task;
4898 #region Get Signed Contracts
4907 return this.GetSignedContracts(this.componentAddress, 0,
int.MaxValue, Callback, State);
4916 public Task
GetSignedContracts(
string Address, EventHandlerAsync<ContractsEventArgs> Callback,
object State)
4918 return this.GetSignedContracts(Address, 0,
int.MaxValue, Callback, State);
4928 public Task
GetSignedContracts(
int Offset,
int MaxCount, EventHandlerAsync<ContractsEventArgs> Callback,
object State)
4930 return this.GetSignedContracts(this.componentAddress, Offset, MaxCount, Callback, State);
4941 public Task
GetSignedContracts(
string Address,
int Offset,
int MaxCount, EventHandlerAsync<ContractsEventArgs> Callback,
object State)
4944 throw new ArgumentException(
"Offsets cannot be negative.", nameof(Offset));
4947 throw new ArgumentException(
"Must be postitive.", nameof(MaxCount));
4949 StringBuilder Xml =
new StringBuilder();
4951 Xml.Append(
"<getSignedContracts references='false' xmlns='");
4952 Xml.Append(NamespaceSmartContractsCurrent);
4956 Xml.Append(
"' offset='");
4957 Xml.Append(Offset.ToString());
4960 if (MaxCount <
int.MaxValue)
4962 Xml.Append(
"' maxCount='");
4963 Xml.Append(MaxCount.ToString());
4968 return this.client.SendIqGet(Address, Xml.ToString(),
this.ContractsResponse,
new object[] { Callback, State });
4977 return this.GetSignedContractsAsync(this.componentAddress, 0,
int.MaxValue);
4988 return this.GetSignedContractsAsync(this.componentAddress, Offset, MaxCount);
5000 TaskCompletionSource<ContractsEventArgs> Result =
new TaskCompletionSource<ContractsEventArgs>();
5002 await this.GetSignedContracts(Address, Offset, MaxCount, (Sender, e) =>
5004 Result.TrySetResult(e);
5005 return Task.CompletedTask;
5009 return await Result.Task;
5014 #region Contract Signature event
5016 private async Task ContractSignedMessageHandler(
object Sender,
MessageEventArgs e)
5025 this.Error(
"Client signature message ignored. Source domain (" +
5026 e.
FromBareJID +
") not equal to contract domain (" +
5033 foreach (XmlNode N
in e.
Content.ChildNodes)
5035 if (N is XmlElement E && E.LocalName ==
"contract" && IsNamespaceSmartContract(E.NamespaceURI))
5045 this.Error(
"Client signature message ignored. Unable to parse embedded contract.");
5055 public event EventHandlerAsync<ContractSignedEventArgs> ContractSigned =
null;
5059 #region Get Contract
5067 public Task
GetContract(
string ContractId, EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
5069 return this.GetContract(this.GetTrustProvider(ContractId), ContractId, Callback, State);
5079 public Task
GetContract(
string Address,
string ContractId, EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
5081 StringBuilder Xml =
new StringBuilder();
5083 Xml.Append(
"<getContract xmlns='");
5084 Xml.Append(NamespaceSmartContractsCurrent);
5085 Xml.Append(
"' id='");
5089 return this.client.SendIqGet(Address, Xml.ToString(),
this.ContractResponse,
new object[] { Callback, State });
5099 return this.GetContractAsync(this.GetTrustProvider(ContractId), ContractId);
5110 TaskCompletionSource<Contract> Result =
new TaskCompletionSource<Contract>();
5112 await this.GetContract(Address, ContractId, (Sender, e) =>
5115 Result.TrySetResult(e.Contract);
5117 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get the contract."));
5119 return Task.CompletedTask;
5123 return await Result.Task;
5128 #region Get Contracts
5136 public async Task
GetContracts(
string[] ContractIds, EventHandlerAsync<ContractsEventArgs> Callback,
object State)
5138 Dictionary<string, List<string>> ByTrustProvider =
new Dictionary<string, List<string>>();
5139 string LastTrustProvider =
string.Empty;
5140 List<string> LastList =
null;
5142 foreach (
string ContractId
in ContractIds)
5144 string TrustProvider = this.GetTrustProvider(ContractId);
5146 if (TrustProvider != LastTrustProvider || LastList is
null)
5148 if (!ByTrustProvider.TryGetValue(TrustProvider, out LastList))
5150 LastList =
new List<string>();
5151 ByTrustProvider[TrustProvider] = LastList;
5154 LastTrustProvider = TrustProvider;
5157 LastList.Add(ContractId);
5160 List<Contract> Contracts =
new List<Contract>();
5161 List<string> References =
new List<string>();
5163 int NrLeft = ByTrustProvider.Count;
5165 foreach (KeyValuePair<
string, List<string>> P
in ByTrustProvider)
5167 await this.GetContracts(P.Key, P.Value.ToArray(), async (Sender, e) =>
5173 Contracts.AddRange(e.Contracts);
5174 References.AddRange(e.References);
5189 await Callback.Raise(
this, e2);
5202 public Task
GetContracts(
string Address,
string[] ContractIds, EventHandlerAsync<ContractsEventArgs> Callback,
object State)
5204 StringBuilder Xml =
new StringBuilder();
5206 Xml.Append(
"<getContracts xmlns='");
5207 Xml.Append(NamespaceSmartContractsCurrent);
5210 foreach (
string ContractId
in ContractIds)
5212 Xml.Append(
"<ref id='");
5217 Xml.Append(
"</getContracts>");
5219 return this.client.SendIqGet(Address, Xml.ToString(),
this.ContractsResponse,
new object[] { Callback, State });
5229 TaskCompletionSource<ContractsEventArgs> Result =
new TaskCompletionSource<ContractsEventArgs>();
5231 await this.GetContracts(ContractIds, (Sender, e) =>
5233 Result.TrySetResult(e);
5234 return Task.CompletedTask;
5238 return await Result.Task;
5249 TaskCompletionSource<ContractsEventArgs> Result =
new TaskCompletionSource<ContractsEventArgs>();
5251 await this.GetContracts(Address, ContractIds, (Sender, e) =>
5253 Result.TrySetResult(e);
5254 return Task.CompletedTask;
5258 return await Result.Task;
5263 #region Obsolete Contract
5271 public Task
ObsoleteContract(
string ContractId, EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
5273 return this.ObsoleteContract(this.GetTrustProvider(ContractId), ContractId, Callback, State);
5284 EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
5286 StringBuilder Xml =
new StringBuilder();
5288 Xml.Append(
"<obsoleteContract xmlns='");
5289 Xml.Append(NamespaceSmartContractsCurrent);
5290 Xml.Append(
"' id='");
5294 return this.client.SendIqSet(Address, Xml.ToString(),
this.ContractResponse,
new object[] { Callback, State });
5304 return this.ObsoleteContractAsync(this.GetTrustProvider(ContractId), ContractId);
5315 TaskCompletionSource<Contract> Result =
new TaskCompletionSource<Contract>();
5317 await this.ObsoleteContract(Address, ContractId, (Sender, e) =>
5320 Result.TrySetResult(e.Contract);
5322 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to obsolete the contract."));
5324 return Task.CompletedTask;
5328 return await Result.Task;
5333 #region Delete Contract
5341 public Task
DeleteContract(
string ContractId, EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
5343 return this.DeleteContract(this.GetTrustProvider(ContractId), ContractId, Callback, State);
5354 EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
5356 StringBuilder Xml =
new StringBuilder();
5358 Xml.Append(
"<deleteContract xmlns='");
5359 Xml.Append(NamespaceSmartContractsCurrent);
5360 Xml.Append(
"' id='");
5364 return this.client.SendIqSet(Address, Xml.ToString(),
this.ContractResponse,
new object[] { Callback, State });
5374 return this.DeleteContractAsync(this.GetTrustProvider(ContractId), ContractId);
5385 TaskCompletionSource<Contract> Result =
new TaskCompletionSource<Contract>();
5387 await this.DeleteContract(Address, ContractId, (Sender, e) =>
5390 Result.TrySetResult(e.Contract);
5392 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to delete the contract."));
5394 return Task.CompletedTask;
5398 return await Result.Task;
5403 #region Contract Created event
5405 private Task ContractCreatedMessageHandler(
object Sender,
MessageEventArgs e)
5409 if (!this.IsFromTrustProvider(ContractId, e.
From))
5410 return Task.CompletedTask;
5418 public event EventHandlerAsync<ContractReferenceEventArgs> ContractCreated =
null;
5422 #region Contract Updated event
5424 private Task ContractUpdatedMessageHandler(
object Sender,
MessageEventArgs e)
5428 if (!this.IsFromTrustProvider(ContractId, e.
From))
5429 return Task.CompletedTask;
5437 public event EventHandlerAsync<ContractReferenceEventArgs> ContractUpdated =
null;
5441 #region Contract Deleted event
5443 private Task ContractDeletedMessageHandler(
object Sender,
MessageEventArgs e)
5447 if (!this.IsFromTrustProvider(ContractId, e.
From))
5448 return Task.CompletedTask;
5456 public event EventHandlerAsync<ContractReferenceEventArgs> ContractDeleted =
null;
5460 #region Update Contract
5481 EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
5485 Tuple<SymmetricCipherAlgorithms, string, byte[]> KeyInfo =
5488 if (!(KeyInfo is
null))
5497 StringBuilder Xml =
new StringBuilder();
5499 Xml.Append(
"<updateContract xmlns='");
5500 Xml.Append(NamespaceSmartContractsCurrent);
5505 Xml.Append(
"</updateContract>");
5507 await this.client.SendIqSet(Address, Xml.ToString(),
this.ContractResponse,
new object[] { Callback, State });
5528 TaskCompletionSource<Contract> Result =
new TaskCompletionSource<Contract>();
5530 await this.UpdateContract(Address,
Contract, (Sender, e) =>
5533 Result.TrySetResult(e.Contract);
5535 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to update the contract."));
5537 return Task.CompletedTask;
5541 return await Result.Task;
5546 #region Validate Contract
5556 return this.Validate(
Contract,
true,
true,
true,
true, Callback, State);
5568 return this.Validate(
Contract, ValidateState,
true,
true,
true, Callback, State);
5583 bool ValidateIdentities,
bool ValidateIdentityAttachments,
5584 EventHandlerAsync<ContractValidationEventArgs> Callback,
object State)
5588 await this.ReturnStatus(
ContractStatus.ContractUndefined, Callback, State);
5592 if (ValidateState &&
5597 await this.ReturnStatus(
ContractStatus.NotApproved, Callback, State,
5602 DateTime UtcNow = DateTime.UtcNow;
5606 await this.ReturnStatus(
ContractStatus.NotValidYet, Callback, State,
5607 new KeyValuePair<string, object>(
"From",
Contract.
From));
5613 await this.ReturnStatus(
ContractStatus.NotValidAnymore, Callback, State,
5614 new KeyValuePair<string, object>(
"To",
Contract.
To));
5620 await this.ReturnStatus(
ContractStatus.NoTrustProvider, Callback, State);
5626 await this.ReturnStatus(
ContractStatus.TemplateOnly, Callback, State);
5632 await this.ReturnStatus(
ContractStatus.NoClientSignatures, Callback, State);
5638 await this.ReturnStatus(
ContractStatus.NotLegallyBinding, Callback, State);
5642 if (!await IsHumanReadableWellDefined(
Contract))
5644 await this.ReturnStatus(
ContractStatus.HumanReadableNotWellDefined, Callback, State);
5654 {
"Duration", Contract.Duration }
5658 if (FirstSignature.HasValue)
5660 Variables[
"Now"] = FirstSignature.Value.ToLocalTime();
5661 Variables[
"NowUtc"] = FirstSignature.Value.ToUniversalTime();
5681 if (!(Tags is
null))
5683 await this.ReturnStatus(
ContractStatus.ParameterValuesNotValid, Callback,
5684 State, Tags.ToArray());
5690 await this.ReturnStatus(
ContractStatus.NoResponse, Callback, State,
5691 new KeyValuePair<string, object>(
"Error", ex.Message));
5694 catch (Exception ex)
5696 await this.ReturnStatus(
ContractStatus.ParameterValuesNotValid, Callback, State,
5697 new KeyValuePair<string, object>(
"Error", ex.Message));
5708 await this.ReturnStatus(
ContractStatus.MachineReadableNotWellDefined, Callback, State);
5718 catch (Exception ex)
5720 await this.ReturnStatus(
ContractStatus.MachineReadableNotWellDefined, Callback, State,
5721 new KeyValuePair<string, object>(
"Error", ex.Message));
5725 Dictionary<string, XmlSchema> Schemas =
new Dictionary<string, XmlSchema>();
5731 string LastNamespace =
null;
5738 Namespace = E.NamespaceURI;
5739 if (!
string.IsNullOrEmpty(Namespace) && Namespace != LastNamespace)
5741 Schemas[Namespace] =
null;
5742 LastNamespace = Namespace;
5745 if (E.HasAttributes)
5747 foreach (XmlAttribute Attr
in E.Attributes)
5749 Namespace = Attr.NamespaceURI;
5751 if (!
string.IsNullOrEmpty(Namespace) &&
5752 Namespace != LastNamespace &&
5753 Namespace !=
"http://www.w3.org/XML/1998/namespace" &&
5754 Namespace !=
"http://www.w3.org/2000/xmlns/")
5756 Schemas[Namespace] =
null;
5761 foreach (XmlNode N
in E.ChildNodes)
5763 if (N is XmlElement E2)
5768 int NrSchemas = Schemas.Count;
5771 await this.ReturnStatus(
ContractStatus.MachineReadableNotWellDefined, Callback, State,
5776 Tuple<XmlSchema, ContractStatus?, Exception> SchemaResult;
5781 if (SchemaResult.Item2.HasValue)
5783 await this.ReturnStatus(SchemaResult.Item2.Value, Callback, State,
5784 new KeyValuePair<string, object>(
"Error", SchemaResult.Item3?.Message ??
string.Empty),
5790 else if (SchemaResult.Item1 is
null)
5792 await this.ReturnStatus(
ContractStatus.NoSchemaAccess, Callback, State);
5797 Schema = SchemaResult.Item1;
5801 string[] Namespaces =
new string[Schemas.Count];
5802 Schemas.Keys.CopyTo(Namespaces, 0);
5804 string ContractComponent;
5807 ContractComponent = this.componentAddress;
5811 foreach (
string Namespace2
in Namespaces)
5813 if (Schemas.TryGetValue(Namespace2, out Schema) && !(Schema is
null))
5816 SchemaResult = await this.LoadSchema(this.componentAddress, Namespace2,
null,
null);
5818 if (SchemaResult.Item2.HasValue)
5820 await this.ReturnStatus(SchemaResult.Item2.Value, Callback, State,
5821 new KeyValuePair<string, object>(
"Error", SchemaResult.Item3?.Message ??
string.Empty),
5822 new KeyValuePair<string, object>(
"Namespace", Namespace2));
5825 else if (SchemaResult.Item1 is
null)
5827 await this.ReturnStatus(
ContractStatus.NoSchemaAccess, Callback, State,
5828 new KeyValuePair<string, object>(
"Namespace", Namespace2));
5833 Schema = SchemaResult.Item1;
5834 Schemas[Namespace2] = Schema;
5840 XmlSchema[] Schemas2 =
new XmlSchema[Schemas.Count];
5841 Schemas.Values.CopyTo(Schemas2, 0);
5845 catch (XmlSchemaException ex)
5849 Log.
Debug(
"Unable to validate Machine-readable content. Following events record the contents of the operation.");
5850 Log.
Debug(
"Error:\r\n\r\n```\r\n" + ex.Message +
"\r\n```");
5851 Log.
Debug(
"XML:\r\n\r\n```\r\n" + Doc.OuterXml +
"\r\n```");
5853 foreach (KeyValuePair<string, XmlSchema> P
in Schemas)
5855 using MemoryStream ms =
new MemoryStream();
5858 Log.
Debug(
"`" + P.Key +
"`\r\n\r\n```\r\n" +
5859 Encoding.UTF8.GetString(ms.ToArray()) +
"\r\n```");
5864 await this.ReturnStatus(
ContractStatus.FraudulentMachineReadable, Callback, State,
5865 new KeyValuePair<string, object>(
"Error", ex.Message));
5869 catch (Exception ex)
5873 await this.ReturnStatus(
ContractStatus.FraudulentMachineReadable, Callback, State,
5874 new KeyValuePair<string, object>(
"Error", ex.Message));
5879 StringBuilder Xml =
new StringBuilder();
5881 byte[] Data = Encoding.UTF8.GetBytes(Xml.ToString());
5882 Dictionary<string, LegalIdentity> Identities =
new Dictionary<string, LegalIdentity>();
5884 if (ValidateIdentities)
5888 if (Identities.ContainsKey(
Signature.LegalId))
5894 if (Identity is
null)
5898 await this.ReturnStatus(
ContractStatus.NoResponse, Callback, State,
5899 new KeyValuePair<string, object>(
"LegalId",
Signature.LegalId));
5901 else if (!(P.Value is
null))
5903 await this.ReturnStatus(
ContractStatus.ClientSignatureNotValidated, Callback, State,
5904 new KeyValuePair<string, object>(
"LegalId",
Signature.LegalId),
5905 new KeyValuePair<string, object>(
"Exception", P.Value.GetType().FullName),
5906 new KeyValuePair<string, object>(
"Message", P.Value.Message));
5910 await this.ReturnStatus(
ContractStatus.ClientSignatureInvalid, Callback, State,
5911 new KeyValuePair<string, object>(
"LegalId",
Signature.LegalId),
5912 new KeyValuePair<string, object>(
"DataBase64", Convert.ToBase64String(Data)),
5921 await this.ReturnStatus(
ContractStatus.ClientIdentityInvalid, Callback,
5923 new KeyValuePair<string, object>(
"IdentityStatus", e.
Status),
5924 new KeyValuePair<string, object>(
"LegalId", Identity.
Id)));
5928 Identities[
Signature.LegalId] = Identity;
5938 await this.ReturnStatus(
ContractStatus.AttachmentLacksUrl, Callback, State,
5939 new KeyValuePair<string, object>(
"AttachmentId",
Attachment.
Id));
5945 KeyValuePair<string, TemporaryFile> P = await this.GetAttachmentAsync(
Attachment.
Url,
SignWith.LatestApprovedId, 30000);
5951 await this.ReturnStatus(
ContractStatus.AttachmentInconsistency, Callback, State,
5952 new KeyValuePair<string, object>(
"AttachmentId",
Attachment.
Id),
5953 new KeyValuePair<string, object>(
"AttachmentUrl",
Attachment.
Url),
5955 new KeyValuePair<string, object>(
"ContentType", P.Key));
5965 MemoryStream ms =
new MemoryStream();
5966 await File.CopyToAsync(ms);
5967 Data = ms.ToArray();
5981 if (IsValid.HasValue)
5985 await this.ReturnStatus(
ContractStatus.AttachmentSignatureInvalid, Callback, State,
5986 new KeyValuePair<string, object>(
"AttachmentId",
Attachment.
Id),
5987 new KeyValuePair<string, object>(
"AttachmentUrl",
Attachment.
Url),
5988 new KeyValuePair<string, object>(
"AttachmentSignatureBase64", Convert.ToBase64String(
Attachment.
Signature)));
5994 await this.ReturnStatus(
ContractStatus.AttachmentSignatureInvalid, Callback, State,
5995 new KeyValuePair<string, object>(
"AttachmentId",
Attachment.
Id),
5996 new KeyValuePair<string, object>(
"AttachmentUrl",
Attachment.
Url),
5997 new KeyValuePair<string, object>(
"KeyName", Identity.ClientKeyName));
6001 catch (Exception ex)
6003 await this.ReturnStatus(
ContractStatus.AttachmentUnavailable, Callback, State,
6004 new KeyValuePair<string, object>(
"AttachmentId",
Attachment.
Id),
6005 new KeyValuePair<string, object>(
"AttachmentUrl",
Attachment.
Url),
6006 new KeyValuePair<string, object>(
"Error", ex.Message));
6014 await this.ReturnStatus(
ContractStatus.NoProviderSignature, Callback, State);
6020 Data = Encoding.UTF8.GetBytes(Xml.ToString());
6027 if (e.
Ok && !(e.Key is
null))
6029 bool Valid = e.Key.Verify(Data, Contract.ServerSignature.DigitalSignature);
6033 await this.ReturnStatus(ContractStatus.Valid, Callback, State);
6037 if (!HasOldPublicKey)
6039 await this.ReturnStatus(
ContractStatus.ProviderSignatureInvalid, Callback, State,
6041 new KeyValuePair<string, object>(
"LocalName", e.Key.LocalName),
6042 new KeyValuePair<string, object>(
"Namespace", e.Key.Namespace),
6043 new KeyValuePair<string, object>(
"PublicKeyBase64", e.Key.PublicKeyBase64),
6044 new KeyValuePair<string, object>(
"DataBase64", Convert.ToBase64String(Data)),
6054 if (e2.Ok && !(e2.Key is null))
6056 if (e.Key.Equals(e2.Key))
6058 return this.ReturnStatus(ContractStatus.ProviderSignatureInvalid, Callback, State,
6059 new KeyValuePair<string, object>(
"Provider", Contract.Provider),
6060 new KeyValuePair<string, object>(
"LocalName", e.Key.LocalName),
6061 new KeyValuePair<string, object>(
"Namespace", e.Key.Namespace),
6062 new KeyValuePair<string, object>(
"PublicKeyBase64", e.Key.PublicKeyBase64),
6063 new KeyValuePair<string, object>(
"DataBase64", Convert.ToBase64String(Data)),
6064 new KeyValuePair<string, object>(
"SignatureBase64", Convert.ToBase64String(Contract.ServerSignature.DigitalSignature)));
6067 Valid = e2.Key.Verify(Data, Contract.ServerSignature.DigitalSignature);
6070 return this.ReturnStatus(ContractStatus.Valid, Callback, State);
6072 return this.ReturnStatus(ContractStatus.ProviderSignatureInvalid, Callback, State);
6076 return this.ReturnStatus(ContractStatus.NoProviderPublicKey, Callback, State,
6077 new KeyValuePair<string, object>(
"Provider", Contract.Provider),
6078 new KeyValuePair<string, object>(
"ErrorText", e2.ErrorText));
6085 await this.ReturnStatus(
ContractStatus.NoProviderPublicKey, Callback, State,
6087 new KeyValuePair<string, object>(
"ErrorText", e.
ErrorText));
6093 private async Task<Tuple<XmlSchema, ContractStatus?, Exception>> LoadSchema(
string ContractComponent,
string Namespace,
6102 if (this.schemas.TryGetValue(SchemaKey, out Tuple<
byte[], XmlSchema, DateTime> P) &&
6103 P.Item3 >= DateTime.UtcNow)
6105 return new Tuple<XmlSchema, ContractStatus?, Exception>(P.Item2,
null,
null);
6112 await GetLocalSchema.Raise(
this, e,
false);
6121 this.schemas[SchemaKey] =
new Tuple<byte[], XmlSchema, DateTime>(SchemaBin, Schema, DateTime.UtcNow.AddDays(CacheSchemaDays));
6124 return new Tuple<XmlSchema, ContractStatus?, Exception>(Schema,
null,
null);
6127 if (
string.IsNullOrEmpty(ContractComponent))
6128 ContractComponent = this.componentAddress;
6132 SchemaBin = await this.GetSchemaAsync(ContractComponent, Namespace,
6135 catch (Exception ex)
6137 return new Tuple<XmlSchema, ContractStatus?, Exception>(
null,
ContractStatus.NoSchemaAccess, ex);
6144 if (Convert.ToBase64String(Digest) != Convert.ToBase64String(
SchemaDigest))
6145 return new Tuple<XmlSchema, ContractStatus?, Exception>(
null,
ContractStatus.FraudulentSchema,
null);
6152 catch (Exception ex)
6154 return new Tuple<XmlSchema, ContractStatus?, Exception>(
null,
ContractStatus.CorruptSchema, ex);
6159 this.schemas[SchemaKey] =
new Tuple<byte[], XmlSchema, DateTime>(SchemaBin, Schema, DateTime.UtcNow.AddDays(CacheSchemaDays));
6162 return new Tuple<XmlSchema, ContractStatus?, Exception>(Schema,
null,
null);
6168 public static event EventHandlerAsync<SchemaReferenceEventArgs> GetLocalSchema =
null;
6170 private readonly Dictionary<string, Tuple<byte[], XmlSchema, DateTime>> schemas =
new Dictionary<string, Tuple<byte[], XmlSchema, DateTime>>();
6172 private Task ReturnStatus(
ContractStatus Status, EventHandlerAsync<ContractValidationEventArgs> Callback,
object State,
6173 params KeyValuePair<string, object>[] Tags)
6178 private static async Task<bool> IsHumanReadableWellDefined(
HumanReadableText[] Texts)
6192 private static async Task<bool> IsHumanReadableWellDefined(
Contract Contract)
6225 return this.ValidateAsync(
Contract,
true,
true,
true,
true);
6236 return this.ValidateAsync(
Contract, ValidateState,
true,
true,
true);
6250 bool ValidateState,
bool ValidateAttachments,
6251 bool ValidateIdentities,
bool ValidateIdentityAttachments)
6253 TaskCompletionSource<ContractValidationEventArgs> Result =
new TaskCompletionSource<ContractValidationEventArgs>();
6255 await this.Validate(
Contract, ValidateState, ValidateAttachments,
6256 ValidateIdentities, ValidateIdentityAttachments, (Sender, e) =>
6258 Result.TrySetResult(e);
6259 return Task.CompletedTask;
6262 return await Result.Task;
6281 if (ReferenceDomain != SignatoryDomain)
6284 TaskCompletionSource<bool> Result =
new TaskCompletionSource<bool>();
6285 StringBuilder Xml =
new StringBuilder();
6287 Xml.Append(
"<canSignAs xmlns='");
6288 Xml.Append(NamespaceLegalIdentitiesCurrent);
6289 Xml.Append(
"' referenceId='");
6291 Xml.Append(
"' signatoryId='");
6295 await this.client.SendIqGet(ReferenceDomain, Xml.ToString(), (
_, e) =>
6297 Result.TrySetResult(e.Ok);
6298 return Task.CompletedTask;
6301 return await Result.Task;
6306 #region SendContractProposal
6317 return this.SendContractProposal(
Contract,
Role, To,
string.Empty);
6332 Tuple<SymmetricCipherAlgorithms, string, byte[]> T = await this.TryLoadContractSharedSecret(
Contract.
ContractId);
6352 return this.SendContractProposal(ContractId,
Role, To,
string.Empty);
6379 StringBuilder Xml =
new StringBuilder();
6381 Xml.Append(
"<contractProposal xmlns=\"");
6382 Xml.Append(NamespaceSmartContractsCurrent);
6383 Xml.Append(
"\" contractId=\"");
6385 Xml.Append(
"\" role=\"");
6388 if (!
string.IsNullOrEmpty(Message))
6390 Xml.Append(
"\" message=\"");
6403 string.Empty, To, Xml.ToString(),
string.Empty,
string.Empty,
string.Empty,
string.Empty,
string.Empty,
null,
null);
6407 await this.client.SendMessage(
MessageType.Normal, To, Xml.ToString(),
string.Empty,
string.Empty,
string.Empty,
6408 string.Empty,
string.Empty);
6413 Xml.Append(
"><sharedSecret key=\"");
6414 Xml.Append(Convert.ToBase64String(Key));
6415 Xml.Append(
"\" algorithm=\"");
6417 switch (KeyAlgorithm)
6432 throw new ArgumentException(
"Algorithm not recognized.", nameof(KeyAlgorithm));
6435 Xml.Append(
"\"/></contractProposal>");
6438 throw new InvalidOperationException(
"End-to-End encryption not enabled.");
6443 ??
throw new ArgumentException(
"Recipient not in roster.", nameof(To));
6446 if (
string.IsNullOrEmpty(To))
6447 throw new ArgumentException(
"Recipient not online.", nameof(To));
6451 string.Empty, To, Xml.ToString(),
string.Empty,
string.Empty,
string.Empty,
string.Empty,
string.Empty,
null,
null);
6455 private async Task ContractProposalMessageHandler(
object Sender,
MessageEventArgs e)
6463 foreach (XmlNode N
in e.
Content.ChildNodes)
6465 if (N is XmlElement E && E.LocalName ==
"sharedSecret" && E.NamespaceURI == e.
Content.NamespaceURI)
6469 this.client.Error(
"Confidential Proposal not sent using end-to-end encryption. Message discarded.");
6475 Key = Convert.FromBase64String(
XML.
Attribute(E,
"key"));
6479 this.client.Error(
"Invalid base64-encoded shared secret. Message discarded.");
6500 this.client.Error(
"Unrecognized key algorithm. Message discarded.");
6507 await this.SaveContractSharedSecret(ContractId, e.
FromBareJID, Key, KeyAlgorithm,
true);
6512 internal async Task<bool> SaveContractSharedSecret(
string ContractId,
string CreatorJid,
byte[] Key,
6522 if (!(await this.TryLoadLegacyContractSharedSecretAsync(ContractId,
true) is
null))
6526 return await this.UpsertContractStateAsync(ContractId, CreatorJid, Key, KeyAlgorithm);
6529 internal async Task<Tuple<SymmetricCipherAlgorithms, string, byte[]>> TryLoadContractSharedSecret(
string ContractId)
6532 Tuple<SymmetricCipherAlgorithms, string, byte[]> Result = this.TryLoadContractSharedSecret(State);
6534 if (!(Result is
null))
6537 if (!(State is
null))
6540 return await this.TryLoadLegacyContractSharedSecretAsync(ContractId,
true);
6546 public event EventHandlerAsync<ContractProposalEventArgs> ContractProposalReceived =
null;
6557 public Task
GetSchemas(EventHandlerAsync<SchemaReferencesEventArgs> Callback,
object State)
6559 return this.GetSchemas(this.componentAddress, Callback, State);
6568 public Task
GetSchemas(
string Address, EventHandlerAsync<SchemaReferencesEventArgs> Callback,
object State)
6570 return this.client.SendIqGet(Address,
"<getSchemas xmlns='" + NamespaceSmartContractsCurrent +
"'/>",
6571 async (Sender, e) =>
6573 XmlElement E = e.FirstElement;
6574 List<SchemaReference> Schemas =
new List<SchemaReference>();
6576 if (e.
Ok && !(E is
null) && E.LocalName ==
"schemas")
6578 foreach (XmlNode N
in E.ChildNodes)
6580 if (N is XmlElement E2 && E2.LocalName ==
"schemaRef")
6583 List<SchemaDigest> Digests =
new List<SchemaDigest>();
6585 foreach (XmlNode N2
in E2.ChildNodes)
6587 if (N2 is XmlElement E3 && E3.LocalName ==
"digest")
6592 byte[] Digest = Convert.FromBase64String(E3.InnerText);
6616 return this.GetSchemasAsync(this.componentAddress);
6626 TaskCompletionSource<SchemaReference[]> Result =
new TaskCompletionSource<SchemaReference[]>();
6628 await this.GetSchemas(Address, (Sender, e) =>
6631 Result.TrySetResult(e.References);
6633 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get schemas."));
6635 return Task.CompletedTask;
6639 return await Result.Task;
6652 public Task
GetSchema(
string Namespace, EventHandlerAsync<SchemaEventArgs> Callback,
object State)
6654 return this.GetSchema(this.componentAddress, Namespace,
null, Callback, State);
6666 return this.GetSchema(this.componentAddress, Namespace, Digest, Callback, State);
6676 public Task
GetSchema(
string Address,
string Namespace, EventHandlerAsync<SchemaEventArgs> Callback,
object State)
6678 return this.GetSchema(Address, Namespace,
null, Callback, State);
6689 public async Task
GetSchema(
string Address,
string Namespace,
SchemaDigest Digest, EventHandlerAsync<SchemaEventArgs> Callback,
object State)
6692 await GetLocalSchema.Raise(
this, e,
false);
6696 if (!(Callback is
null))
6698 XmlDocument Doc =
new XmlDocument();
6699 XmlElement Empty = Doc.CreateElement(
"Local");
6703 await Callback.Raise(
this, e2);
6709 StringBuilder Xml =
new StringBuilder();
6711 Xml.Append(
"<getSchema xmlns='");
6712 Xml.Append(NamespaceSmartContractsCurrent);
6713 Xml.Append(
"' namespace='");
6720 Xml.Append(
"'><digest function='");
6721 Xml.Append(Digest.
Function.ToString());
6723 Xml.Append(Convert.ToBase64String(Digest.
Digest));
6724 Xml.Append(
"</digest></getSchema>");
6727 await this.client.SendIqGet(Address, Xml.ToString(),
6728 async (Sender, e) =>
6730 XmlElement E = e.FirstElement;
6731 byte[] Schema =
null;
6733 if (e.Ok && !(E is
null) && E.LocalName ==
"schema")
6734 Schema = Convert.FromBase64String(E.InnerText);
6750 return this.GetSchemaAsync(this.componentAddress, Namespace,
null);
6761 return this.GetSchemaAsync(this.componentAddress, Namespace, Digest);
6772 return this.GetSchemaAsync(Address, Namespace,
null);
6784 TaskCompletionSource<byte[]> Result =
new TaskCompletionSource<byte[]>();
6786 await this.GetSchema(Address, Namespace, Digest, (Sender, e) =>
6789 Result.TrySetResult(e.Schema);
6791 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get schema."));
6793 return Task.CompletedTask;
6797 return await Result.Task;
6802 #region Get Legal Identities of a contract
6812 return this.GetContractLegalIdentities(this.GetTrustProvider(ContractId), ContractId,
false,
true, Callback, State);
6823 public Task
GetContractLegalIdentities(
string ContractId,
bool Current,
bool Historic, EventHandlerAsync<LegalIdentitiesEventArgs> Callback,
object State)
6825 return this.GetContractLegalIdentities(this.GetTrustProvider(ContractId), ContractId, Current, Historic, Callback, State);
6837 return this.GetContractLegalIdentities(Address, ContractId,
false,
true, Callback, State);
6849 public Task
GetContractLegalIdentities(
string Address,
string ContractId,
bool Current,
bool Historic, EventHandlerAsync<LegalIdentitiesEventArgs> Callback,
object State)
6851 StringBuilder Xml =
new StringBuilder();
6853 Xml.Append(
"<getLegalIdentities xmlns='");
6854 Xml.Append(NamespaceSmartContractsCurrent);
6855 Xml.Append(
"' contractId='");
6857 Xml.Append(
"' current='");
6859 Xml.Append(
"' historic='");
6863 return this.client.SendIqGet(Address, Xml.ToString(),
this.IdentitiesResponse,
new object[] { Callback, State });
6873 return this.GetContractLegalIdentitiesAsync(this.GetTrustProvider(ContractId), ContractId,
false,
true);
6885 return this.GetContractLegalIdentitiesAsync(this.GetTrustProvider(ContractId), ContractId, Current, Historic);
6896 return this.GetContractLegalIdentitiesAsync(Address, ContractId,
false,
true);
6909 TaskCompletionSource<LegalIdentity[]> Result =
new TaskCompletionSource<LegalIdentity[]>();
6911 await this.GetContractLegalIdentities(Address, ContractId, Current, Historic, (Sender, e) =>
6914 Result.TrySetResult(e.Identities);
6916 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get legal identities."));
6918 return Task.CompletedTask;
6922 return await Result.Task;
6927 #region Get Network Identities of a contract
6937 return this.GetContractNetworkIdentities(this.GetTrustProvider(ContractId), ContractId, Callback, State);
6949 StringBuilder Xml =
new StringBuilder();
6951 Xml.Append(
"<getNetworkIdentities xmlns='");
6952 Xml.Append(NamespaceSmartContractsCurrent);
6953 Xml.Append(
"' contractId='");
6957 return this.client.SendIqGet(Address, Xml.ToString(), async (Sender, e) =>
6962 if (e.
Ok && !((E = e.FirstElement) is
null) && E.LocalName ==
"networkIdentities")
6964 List<NetworkIdentity> IdentitiesList = new List<NetworkIdentity>();
6966 foreach (XmlNode N in E.ChildNodes)
6968 if (N is XmlElement E2 && E2.LocalName ==
"networkIdentity")
6970 string BareJid = XML.Attribute(E2,
"bareJid");
6971 string LegalId = XML.Attribute(E2,
"legalId");
6973 IdentitiesList.Add(new NetworkIdentity(BareJid, LegalId));
6977 Identities = IdentitiesList.ToArray();
6993 return this.GetContractNetworkIdentitiesAsync(this.GetTrustProvider(ContractId), ContractId);
7004 TaskCompletionSource<NetworkIdentity[]> Result =
new TaskCompletionSource<NetworkIdentity[]>();
7006 await this.GetContractNetworkIdentities(Address, ContractId, (Sender, e) =>
7009 Result.TrySetResult(e.Identities);
7011 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get network identities."));
7013 return Task.CompletedTask;
7017 return await Result.Task;
7022 #region Search Public Contracts
7032 return this.Search(this.componentAddress, 0,
int.MaxValue,
Filter, Callback, State);
7044 return this.Search(Address, 0,
int.MaxValue,
Filter, Callback, State);
7057 return this.Search(this.componentAddress, Offset, MaxCount,
Filter, Callback, State);
7069 public Task
Search(
string Address,
int Offset,
int MaxCount,
SearchFilter[]
Filter, EventHandlerAsync<SearchResultEventArgs> Callback,
object State)
7072 throw new ArgumentException(
"Offsets cannot be negative.", nameof(Offset));
7075 throw new ArgumentException(
"Must be postitive.", nameof(MaxCount));
7077 StringBuilder Xml =
new StringBuilder();
7079 Xml.Append(
"<searchPublicContracts xmlns='");
7080 Xml.Append(NamespaceSmartContractsCurrent);
7084 Xml.Append(
"' offset='");
7085 Xml.Append(Offset.ToString());
7088 if (MaxCount <
int.MaxValue)
7090 Xml.Append(
"' maxCount='");
7091 Xml.Append(MaxCount.ToString());
7097 Array.Sort(
Filter, (f1, f2) => f1.Order - f2.Order);
7100 int PrevOrderCount = 0;
7106 if (Order != PrevOrder)
7114 if (PrevOrderCount >= F.MaxOccurs)
7116 throw new ArgumentException(
"Maximum number of occurrences of " + F.GetType().FullName +
" in a search is " +
7117 F.MaxOccurs.ToString() +
".", nameof(
Filter));
7124 Xml.Append(
"</searchPublicContracts>");
7126 return this.client.SendIqGet(Address, Xml.ToString(), async (Sender, e) =>
7128 XmlElement E = e.FirstElement;
7129 List<string> IDs =
null;
7132 if (e.
Ok && !(E is
null) && E.LocalName ==
"searchResult")
7134 More = XML.Attribute(E,
"more", false);
7135 IDs = new List<string>();
7137 foreach (XmlNode N in E.ChildNodes)
7139 if (N is XmlElement E2 && E2.LocalName ==
"ref")
7141 string Id = XML.Attribute(E2,
"id");
7160 return this.SearchAsync(this.componentAddress, 0,
int.MaxValue,
Filter);
7170 return this.SearchAsync(Address, 0,
int.MaxValue,
Filter);
7181 return this.SearchAsync(this.componentAddress, Offset, MaxCount,
Filter);
7193 TaskCompletionSource<SearchResultEventArgs> Result =
new TaskCompletionSource<SearchResultEventArgs>();
7195 await this.Search(Address, Offset, MaxCount,
Filter, (Sender, e) =>
7197 Result.TrySetResult(e);
7198 return Task.CompletedTask;
7201 return await Result.Task;
7206 #region Identity petitions
7220 return this.PetitionIdentityAsync(this.GetTrustProvider(LegalId), LegalId, PetitionId, Purpose,
null,
null,
null);
7236 return this.PetitionIdentityAsync(Address, LegalId, PetitionId, Purpose,
null,
null,
null);
7253 return this.PetitionIdentityAsync(Address, LegalId, PetitionId, Purpose, ContextXml,
null,
null);
7271 string[] Properties,
string[] Attachments)
7273 return this.PetitionIdentityAsync(this.GetTrustProvider(LegalId), LegalId, PetitionId, Purpose,
null,
7274 Properties, Attachments);
7293 string[] Properties,
string[] Attachments)
7295 return this.PetitionIdentityAsync(Address, LegalId, PetitionId, Purpose,
null,
7296 Properties, Attachments);
7315 public async Task
PetitionIdentityAsync(
string Address,
string LegalId,
string PetitionId,
string Purpose,
string ContextXml,
7316 string[] Properties,
string[] Attachments)
7318 StringBuilder Xml =
new StringBuilder();
7319 byte[] Nonce = this.RandomBytes(32);
7321 string NonceStr = Convert.ToBase64String(Nonce);
7322 byte[] Data = Encoding.UTF8.GetBytes(PetitionId +
":" + LegalId +
":" + Purpose +
":" + NonceStr +
":" + this.client.BareJID.ToLower());
7325 Xml.Append(
"<petitionIdentity xmlns='");
7326 Xml.Append(NamespaceLegalIdentitiesCurrent);
7327 Xml.Append(
"' id='");
7329 Xml.Append(
"' pid='");
7331 Xml.Append(
"' purpose='");
7333 Xml.Append(
"' nonce='");
7334 Xml.Append(NonceStr);
7335 Xml.Append(
"' s='");
7336 Xml.Append(Convert.ToBase64String(
Signature));
7338 if (
string.IsNullOrEmpty(ContextXml))
7343 AppendHints(Xml, Properties, Attachments);
7344 Xml.Append(ContextXml);
7345 Xml.Append(
"</petitionIdentity>");
7348 await this.client.IqSetAsync(Address, Xml.ToString());
7351 private static void AppendHints(StringBuilder Xml,
string[] Properties,
string[] Attachments)
7353 if (!(Properties is
null))
7355 Xml.Append(
"<properties>");
7357 foreach (
string Property in Properties)
7359 Xml.Append(
"<property>");
7361 Xml.Append(
"</property>");
7364 Xml.Append(
"</properties>");
7367 if (!(Attachments is
null))
7369 Xml.Append(
"<attachments>");
7373 Xml.Append(
"<attachment>");
7375 Xml.Append(
"</attachment>");
7378 Xml.Append(
"</attachments>");
7394 return this.PetitionIdentityResponseAsync(this.GetTrustProvider(LegalId), LegalId, PetitionId, RequestorFullJid, Response,
null);
7410 return this.PetitionIdentityResponseAsync(this.GetTrustProvider(LegalId), LegalId, PetitionId, RequestorFullJid, Response, ContextXml);
7426 return this.PetitionIdentityResponseAsync(Address, LegalId, PetitionId, RequestorFullJid, Response,
null);
7444 StringBuilder Xml =
new StringBuilder();
7446 Xml.Append(
"<petitionIdentityResponse xmlns='");
7447 Xml.Append(NamespaceLegalIdentitiesCurrent);
7448 Xml.Append(
"' id='");
7450 Xml.Append(
"' pid='");
7452 Xml.Append(
"' jid='");
7453 Xml.Append(
XML.
Encode(RequestorFullJid));
7454 Xml.Append(
"' response='");
7457 if (
string.IsNullOrEmpty(ContextXml))
7462 Xml.Append(ContextXml);
7463 Xml.Append(
"</petitionIdentityResponse>");
7466 await this.client.IqSetAsync(Address, Xml.ToString());
7469 private async Task PetitionIdentityMessageHandler(
object Sender,
MessageEventArgs e)
7477 if (!TryGetContext(e.
Content, out XmlElement Context, out
string _,
7478 out
string[] Properties, out
string[] Attachments, out
LegalIdentity Identity))
7480 this.client.Error(
"Invalid context. Ignoring message.");
7484 if (Identity is
null)
7486 this.client.Error(
"No identity in message. Ignoring message.");
7490 if (
string.Compare(e.
FromBareJID,
this.componentAddress,
true) == 0)
7492 await this.Validate(Identity,
false, async (sender2, e2) =>
7496 this.client.Error(
"Invalid legal identity received and discarded.");
7498 Log.Warning(
"Invalid legal identity received and discarded.", this.client.BareJID, e.From,
7499 new KeyValuePair<string, object>(
"Status", e2.Status));
7504 Identity, From, LegalId, PetitionId, Purpose, ClientEndpoint, Context, Properties, Attachments));
7509 private static bool TryGetContext(XmlElement Query, out XmlElement Context,
7510 out
string Content, out
string[] Properties, out
string[] Attachments,
7515 bool IsIdentityNamespace = IsNamespaceLegalIdentity(Query.NamespaceURI);
7516 bool IsContractNamespace = IsNamespaceSmartContract(Query.NamespaceURI);
7523 foreach (XmlNode N
in Query)
7525 if (!(N is XmlElement E))
7528 if (IsIdentityNamespace)
7530 if (!IsNamespaceLegalIdentity(E.NamespaceURI))
7533 else if (IsContractNamespace)
7535 if (!IsNamespaceSmartContract(E.NamespaceURI))
7540 if (E.NamespaceURI != Query.NamespaceURI)
7544 switch (E.LocalName)
7551 if (
string.IsNullOrEmpty(Content))
7553 Content = E.InnerText;
7560 foreach (XmlNode N2
in E.ChildNodes)
7562 if (!(N2 is XmlElement E2))
7565 if (E2.LocalName ==
"property")
7568 PropertyList.
Add(E2.InnerText);
7576 foreach (XmlNode N2
in E.ChildNodes)
7578 if (!(N2 is XmlElement E2))
7581 if (E2.LocalName ==
"attachment")
7584 AttachmentList.
Add(E2.InnerText);
7592 if (Context is
null)
7599 Properties = PropertyList?.
ToArray();
7600 Attachments = AttachmentList?.
ToArray();
7608 public event EventHandlerAsync<LegalIdentityPetitionEventArgs> PetitionForIdentityReceived =
null;
7610 private async Task PetitionIdentityResponseMessageHandler(
object Sender,
MessageEventArgs e)
7616 XmlElement Context =
null;
7618 foreach (XmlNode N
in e.
Content.ChildNodes)
7620 if (N is XmlElement E)
7622 if (E.LocalName ==
"identity" && E.NamespaceURI == e.
Content.NamespaceURI)
7624 else if (!(Context is
null))
7631 if (!Response ||
string.Compare(e.
FromBareJID, Identity?.Provider ??
string.Empty,
true) == 0)
7638 public event EventHandlerAsync<LegalIdentityPetitionResponseEventArgs> PetitionedIdentityResponseReceived =
null;
7642 #region Signature petitions
7657 return this.PetitionSignatureAsync(this.GetTrustProvider(LegalId), LegalId, Content, PetitionId, Purpose,
false,
null,
null,
null);
7674 return this.PetitionSignatureAsync(Address, LegalId, Content, PetitionId, Purpose,
false,
null,
null,
null);
7690 public Task
PetitionSignatureAsync(
string Address,
string LegalId,
byte[] Content,
string PetitionId,
string Purpose,
string ContextXml)
7692 return this.PetitionSignatureAsync(Address, LegalId, Content, PetitionId, Purpose,
false, ContextXml,
null,
null);
7711 string[] Properties,
string[] Attachments)
7713 return this.PetitionSignatureAsync(this.GetTrustProvider(LegalId), LegalId, Content, PetitionId, Purpose,
false,
null,
7714 Properties, Attachments);
7734 string[] Properties,
string[] Attachments)
7736 return this.PetitionSignatureAsync(Address, LegalId, Content, PetitionId, Purpose,
false,
null,
7737 Properties, Attachments);
7757 public Task
PetitionSignatureAsync(
string Address,
string LegalId,
byte[] Content,
string PetitionId,
string Purpose,
string ContextXml,
7758 string[] Properties,
string[] Attachments)
7760 return this.PetitionSignatureAsync(Address, LegalId, Content, PetitionId, Purpose,
false, ContextXml,
7761 Properties, Attachments);
7764 private async Task PetitionSignatureAsync(
string Address,
string LegalId,
byte[] Content,
string PetitionId,
7765 string Purpose,
bool PeerReview,
string ContextXml,
string[] Properties,
string[] Attachments)
7767 if (this.contentPerPid.TryGetValue(PetitionId, out KeyValuePair<
byte[],
bool> Rec))
7769 if (Convert.ToBase64String(Content) == Convert.ToBase64String(Rec.Key) && PeerReview == Rec.Value)
7772 throw new InvalidOperationException(
"Petition ID must be unique for outstanding petitions.");
7775 this.contentPerPid[PetitionId] =
new KeyValuePair<byte[], bool>(Content, PeerReview);
7777 StringBuilder Xml =
new StringBuilder();
7778 byte[] Nonce = this.RandomBytes(32);
7780 string NonceStr = Convert.ToBase64String(Nonce);
7781 string ContentStr = Convert.ToBase64String(Content);
7782 byte[] Data = Encoding.UTF8.GetBytes(PetitionId +
":" + LegalId +
":" + Purpose +
":" + NonceStr +
":" + this.client.BareJID.ToLower() +
":" + ContentStr);
7785 Xml.Append(
"<petitionSignature xmlns='");
7786 Xml.Append(NamespaceLegalIdentitiesCurrent);
7787 Xml.Append(
"' id='");
7789 Xml.Append(
"' pid='");
7791 Xml.Append(
"' purpose='");
7793 Xml.Append(
"' nonce='");
7794 Xml.Append(NonceStr);
7795 Xml.Append(
"' s='");
7796 Xml.Append(Convert.ToBase64String(
Signature));
7798 AppendHints(Xml, Properties, Attachments);
7800 if (!
string.IsNullOrEmpty(ContentStr))
7802 Xml.Append(
"<content>");
7803 Xml.Append(ContentStr);
7804 Xml.Append(
"</content>");
7807 if (!
string.IsNullOrEmpty(ContextXml))
7808 Xml.Append(ContextXml);
7810 Xml.Append(
"</petitionSignature>");
7812 await this.client.IqSetAsync(Address, Xml.ToString());
7828 byte[]
Signature,
string PetitionId,
string RequestorFullJid,
bool Response)
7830 return this.PetitionSignatureResponseAsync(this.GetTrustProvider(LegalId), LegalId, Content,
Signature, PetitionId,
7831 RequestorFullJid, Response,
null);
7848 byte[]
Signature,
string PetitionId,
string RequestorFullJid,
bool Response,
string ContextXml)
7850 return this.PetitionSignatureResponseAsync(this.GetTrustProvider(LegalId), LegalId, Content,
Signature, PetitionId,
7851 RequestorFullJid, Response, ContextXml);
7868 string PetitionId,
string RequestorFullJid,
bool Response)
7870 return this.PetitionSignatureResponseAsync(Address, LegalId, Content,
Signature, PetitionId, RequestorFullJid, Response,
null);
7888 string PetitionId,
string RequestorFullJid,
bool Response,
string ContextXml)
7890 StringBuilder Xml =
new StringBuilder();
7892 Xml.Append(
"<petitionSignatureResponse xmlns='");
7893 Xml.Append(NamespaceLegalIdentitiesCurrent);
7894 Xml.Append(
"' id='");
7896 Xml.Append(
"' pid='");
7898 Xml.Append(
"' jid='");
7899 Xml.Append(
XML.
Encode(RequestorFullJid));
7900 Xml.Append(
"' response='");
7902 Xml.Append(
"'><content>");
7903 Xml.Append(Convert.ToBase64String(Content));
7904 Xml.Append(
"</content><signature>");
7905 Xml.Append(Convert.ToBase64String(
Signature));
7906 Xml.Append(
"</signature>");
7908 if (!
string.IsNullOrEmpty(ContextXml))
7909 Xml.Append(ContextXml);
7911 Xml.Append(
"</petitionSignatureResponse>");
7913 await this.client.IqSetAsync(Address, Xml.ToString());
7916 private async Task PetitionSignatureMessageHandler(
object Sender,
MessageEventArgs e)
7924 bool PeerReview =
false;
7926 if (!TryGetContext(e.
Content, out XmlElement Context, out
string ContentStr,
7927 out
string[] Properties, out
string[] Attachments, out
LegalIdentity Identity))
7929 this.client.Error(
"Invalid context. Ignoring message.");
7933 if (
string.IsNullOrEmpty(ContentStr))
7935 this.client.Error(
"No content in message to sign. Ignoring message.");
7941 Content = Convert.FromBase64String(ContentStr);
7945 this.client.Error(
"Invalid BASE64-encoded content in message to sign. Ignoring message.");
7949 if (Identity is
null)
7951 string s = Encoding.UTF8.GetString(Content);
7952 if (s.StartsWith(
"<identity") && s.EndsWith(
"</identity>"))
7958 if (Doc.DocumentElement.LocalName ==
"identity")
7976 if (Identity is
null)
7980 if (
string.Compare(e.
FromBareJID,
this.componentAddress,
true) != 0 &&
7986 EventHandlerAsync<SignaturePetitionEventArgs> h = PeerReview ? this.PetitionForPeerReviewIDReceived : this.PetitionForSignatureReceived;
7988 await this.Validate(Identity,
false, async (sender2, e2) =>
7992 this.client.Error(
"Invalid legal identity received and discarded.");
7994 Log.Warning(
"Invalid legal identity received and discarded.", this.client.BareJID, e.From,
7995 new KeyValuePair<string, object>(
"Status", e2.Status));
8001 PetitionId, Purpose, Content, ClientEndpoint, Context, Properties, Attachments));
8009 public event EventHandlerAsync<SignaturePetitionEventArgs> PetitionForSignatureReceived =
null;
8011 private async Task PetitionSignatureResponseMessageHandler(
object Sender,
MessageEventArgs e)
8016 string SignatureStr =
string.Empty;
8019 XmlElement Context =
null;
8021 foreach (XmlNode N
in e.
Content.ChildNodes)
8023 if (N is XmlElement E)
8025 switch (E.LocalName)
8032 SignatureStr = E.InnerText;
8033 Signature = Convert.FromBase64String(SignatureStr);
8037 if (!(Context is
null))
8046 if (!this.contentPerPid.TryGetValue(PetitionId, out KeyValuePair<
byte[],
bool> P))
8048 this.client.Warning(
"Petition ID not recognized: " + PetitionId +
". Response ignored.");
8052 EventHandlerAsync<SignaturePetitionResponseEventArgs> h = P.Value ? this.PetitionedPeerReviewIDResponseReceived : this.PetitionedSignatureResponseReceived;
8056 if (Identity is
null)
8058 this.client.Warning(
"Identity missing. Response ignored.");
8064 this.client.Warning(
"Signature missing. Response ignored.");
8068 bool? Result = this.ValidateSignature(Identity, P.Key,
Signature);
8069 if (!Result.HasValue)
8071 this.client.Warning(
"Unable to validate signature. Response ignored.");
8077 this.client.Warning(
"Invalid signature. Response ignored.");
8082 if (!Response ||
string.Compare(e.
FromBareJID, Identity?.Provider ??
string.Empty,
true) == 0)
8086 this.Client.Information(h.Method.Name);
8092 this.contentPerPid.Remove(PetitionId);
8096 this.client.Warning(
"Sender invalid. Response ignored.");
8102 public event EventHandlerAsync<SignaturePetitionResponseEventArgs> PetitionedSignatureResponseReceived =
null;
8106 #region Peer Review of IDs
8127 return this.PetitionPeerReviewIDAsync(this.GetTrustProvider(LegalId), LegalId, Identity, PetitionId, Purpose);
8150 StringBuilder Xml =
new StringBuilder();
8151 Identity.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true);
8152 byte[] Content = Encoding.UTF8.GetBytes(Xml.ToString());
8154 return this.PetitionSignatureAsync(Address, LegalId, Content, PetitionId, Purpose,
true,
null,
null,
null);
8160 public event EventHandlerAsync<SignaturePetitionEventArgs> PetitionForPeerReviewIDReceived =
null;
8165 public event EventHandlerAsync<SignaturePetitionResponseEventArgs> PetitionedPeerReviewIDResponseReceived =
null;
8177 StringBuilder Xml =
new StringBuilder();
8179 Xml.Append(
"<peerReview s='");
8180 Xml.Append(Convert.ToBase64String(PeerSignature));
8181 Xml.Append(
"' tp='");
8182 Xml.Append(
XML.
Encode(DateTime.UtcNow));
8183 Xml.Append(
"' xmlns='");
8184 Xml.Append(NamespaceLegalIdentitiesCurrent);
8185 Xml.Append(
"'><reviewed>");
8186 Identity.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true);
8187 Xml.Append(
"</reviewed><reviewer>");
8188 ReviewerLegalIdentity.
Serialize(Xml,
true,
true,
true,
true,
true,
true,
true);
8189 Xml.Append(
"</reviewer></peerReview>");
8191 byte[] Data = Encoding.UTF8.GetBytes(Xml.ToString());
8192 string FileName = ReviewerLegalIdentity.Id +
".xml";
8193 string ContentType =
"text/xml; charset=utf-8";
8195 return await this.UploadLegalIdAttachmentAsync(Identity.
Id, FileName, Data, ContentType);
8200 #region Contract petitions
8214 return this.PetitionContractAsync(this.GetTrustProvider(ContractId), ContractId, PetitionId, Purpose,
null);
8230 return this.PetitionContractAsync(Address, ContractId, PetitionId, Purpose,
null);
8245 public async Task
PetitionContractAsync(
string Address,
string ContractId,
string PetitionId,
string Purpose,
string ContextXml)
8247 StringBuilder Xml =
new StringBuilder();
8248 byte[] Nonce = this.RandomBytes(32);
8250 string NonceStr = Convert.ToBase64String(Nonce);
8251 byte[] Data = Encoding.UTF8.GetBytes(PetitionId +
":" + ContractId +
":" + Purpose +
":" + NonceStr +
":" + this.client.BareJID.ToLower());
8254 Xml.Append(
"<petitionContract xmlns='");
8255 Xml.Append(NamespaceSmartContractsCurrent);
8256 Xml.Append(
"' id='");
8258 Xml.Append(
"' pid='");
8260 Xml.Append(
"' purpose='");
8262 Xml.Append(
"' nonce='");
8263 Xml.Append(NonceStr);
8264 Xml.Append(
"' s='");
8265 Xml.Append(Convert.ToBase64String(
Signature));
8267 if (
string.IsNullOrEmpty(ContextXml))
8272 Xml.Append(ContextXml);
8273 Xml.Append(
"</petitionContract>");
8276 await this.client.IqSetAsync(Address, Xml.ToString());
8291 return this.PetitionContractResponseAsync(this.GetTrustProvider(ContractId), ContractId, PetitionId, RequestorFullJid, Response,
null);
8307 return this.PetitionContractResponseAsync(this.GetTrustProvider(ContractId), ContractId, PetitionId, RequestorFullJid, Response, ContextXml);
8323 return this.PetitionContractResponseAsync(Address, ContractId, PetitionId, RequestorFullJid, Response,
null);
8339 bool Response,
string ContextXml)
8341 StringBuilder Xml =
new StringBuilder();
8343 Xml.Append(
"<petitionContractResponse xmlns='");
8344 Xml.Append(NamespaceSmartContractsCurrent);
8345 Xml.Append(
"' id='");
8347 Xml.Append(
"' pid='");
8349 Xml.Append(
"' jid='");
8350 Xml.Append(
XML.
Encode(RequestorFullJid));
8351 Xml.Append(
"' response='");
8354 if (
string.IsNullOrEmpty(ContextXml))
8359 Xml.Append(ContextXml);
8360 Xml.Append(
"</petitionContractResponse>");
8363 await this.client.IqSetAsync(Address, Xml.ToString());
8366 private async Task PetitionContractMessageHandler(
object Sender,
MessageEventArgs e)
8373 int i = ContractId.IndexOf(
'@');
8375 if (!TryGetContext(e.
Content, out XmlElement Context, out
string ContentStr,
8376 out
string[] Properties, out
string[] Attachments, out
LegalIdentity Identity))
8378 this.client.Error(
"Invalid context. Ignoring message.");
8382 if (Identity is
null)
8384 this.client.Error(
"No identity in message. Ignoring message.");
8388 if (!this.IsFromTrustProvider(ContractId, e.
FromBareJID))
8390 this.client.Error(
"Contract not hosted on trust provider. Ignoring message.");
8394 await this.Validate(Identity,
false, async (sender2, e2) =>
8398 this.client.Error(
"Invalid identity received and discarded.");
8400 Log.Warning(
"Invalid identity received and discarded.", this.client.BareJID, e.From,
8401 new KeyValuePair<string, object>(
"Status", e2.Status));
8406 Identity, From, ContractId, PetitionId, Purpose, ClientEndpoint, Context, Properties, Attachments));
8414 public event EventHandlerAsync<ContractPetitionEventArgs> PetitionForContractReceived =
null;
8416 private async Task PetitionContractResponseMessageHandler(
object Sender,
MessageEventArgs e)
8422 XmlElement Context =
null;
8424 foreach (XmlNode N
in e.
Content.ChildNodes)
8426 if (!(N is XmlElement E))
8429 if (E.LocalName ==
"contract" && E.NamespaceURI == e.
Content.NamespaceURI)
8434 else if (!(Context is
null))
8447 public event EventHandlerAsync<ContractPetitionResponseEventArgs> PetitionedContractResponseReceived =
null;
8463 [Obsolete(
"To avoid security issues, use the UploadLegalIdAttachmentAsync method instead.")]
8466 return this.AddLegalIdAttachmentPrivate(LegalId, GetUrl,
Signature, Callback, State);
8469 private Task AddLegalIdAttachmentPrivate(
string LegalId,
string GetUrl,
byte[]
Signature, EventHandlerAsync<LegalIdentityEventArgs> Callback,
object State)
8471 StringBuilder Xml =
new StringBuilder();
8473 Xml.Append(
"<addAttachment xmlns='");
8474 Xml.Append(NamespaceLegalIdentitiesCurrent);
8475 Xml.Append(
"' id='");
8477 Xml.Append(
"' getUrl='");
8479 Xml.Append(
"' s='");
8480 Xml.Append(Convert.ToBase64String(
Signature));
8483 return this.client.SendIqSet(this.componentAddress, Xml.ToString(), async (Sender, e) =>
8488 if (e.
Ok && !((E = e.FirstElement) is
null) && E.LocalName ==
"identity")
8505 [Obsolete(
"To avoid security issues, use the UploadLegalIdAttachmentAsync method instead.")]
8508 return this.AddLegalIdAttachmentAsyncPrivate(LegalId, GetUrl,
Signature);
8511 private async Task<LegalIdentity> AddLegalIdAttachmentAsyncPrivate(
string LegalId,
string GetUrl,
byte[]
Signature)
8513 TaskCompletionSource<LegalIdentity> Result =
new TaskCompletionSource<LegalIdentity>();
8515 await this.AddLegalIdAttachmentPrivate(LegalId, GetUrl,
Signature, (Sender, e) =>
8518 Result.TrySetResult(e.Identity);
8520 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to add attachment."));
8522 return Task.CompletedTask;
8526 return await Result.Task;
8538 string FileName,
byte[] Data,
string ContentType)
8540 using MemoryStream ms =
new MemoryStream(Data);
8541 return await this.UploadLegalIdAttachmentAsync(LegalId, FileName, ms, ContentType);
8553 string FileName, Stream Data,
string ContentType)
8556 throw new InvalidOperationException(
"No HTTP File Upload extension added to the XMPP Client.");
8565 catch (Exception ex)
8567 Log.
Warning(
"File upload preparation failed: " + ex.Message,
8569 new KeyValuePair<string, object>(
"LegalId", LegalId),
8570 new KeyValuePair<string, object>(
"FileName", FileName),
8571 new KeyValuePair<string, object>(
"ContentType", ContentType),
8572 new KeyValuePair<string, object>(
"Size", Data.Length));
8576 ContentType, Data.Length);
8580 throw new IOException(
"Unable to upload attachment " + FileName +
" to broker: " +
8584 await e2.
PUT(Data, ContentType, 10000);
8586 return await this.AddLegalIdAttachmentAsyncPrivate(LegalId, e2.
GetUrl,
Signature);
8598 [Obsolete(
"To avoid security issues, use the UploadContractAttachmentAsync method instead.")]
8601 return this.AddContractAttachmentPrivate(ContractId, GetUrl,
Signature, Callback, State);
8604 private Task AddContractAttachmentPrivate(
string ContractId,
string GetUrl,
byte[]
Signature, EventHandlerAsync<SmartContractEventArgs> Callback,
object State)
8606 StringBuilder Xml =
new StringBuilder();
8608 Xml.Append(
"<addAttachment xmlns='");
8609 Xml.Append(NamespaceSmartContractsCurrent);
8610 Xml.Append(
"' contractId='");
8612 Xml.Append(
"' getUrl='");
8614 Xml.Append(
"' s='");
8615 Xml.Append(Convert.ToBase64String(
Signature));
8618 return this.client.SendIqSet(this.componentAddress, Xml.ToString(), async (Sender, e) =>
8623 if (e.
Ok && !((E = e.FirstElement) is
null) && E.LocalName ==
"contract")
8625 ParsedContract Parsed = await Contract.Parse(E, this, false);
8629 Contract = Parsed.Contract;
8645 [Obsolete(
"To avoid security issues, use the UploadContractAttachmentAsync method instead.")]
8648 return this.AddContractAttachmentAsyncPrivate(ContractId, GetUrl,
Signature);
8651 private async Task<Contract> AddContractAttachmentAsyncPrivate(
string ContractId,
string GetUrl,
byte[]
Signature)
8653 TaskCompletionSource<Contract> Result =
new TaskCompletionSource<Contract>();
8655 await this.AddContractAttachmentPrivate(ContractId, GetUrl,
Signature, (Sender, e) =>
8658 Result.TrySetResult(e.Contract);
8660 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to add attachment."));
8662 return Task.CompletedTask;
8666 return await Result.Task;
8678 string FileName,
byte[] Data,
string ContentType)
8680 using MemoryStream ms =
new MemoryStream(Data);
8681 return await this.UploadContractAttachmentAsync(ContractId, FileName, ms, ContentType);
8693 string FileName, Stream Data,
string ContentType)
8696 throw new InvalidOperationException(
"No HTTP File Upload extension added to the XMPP Client.");
8705 catch (Exception ex)
8707 Log.
Warning(
"File upload preparation failed: " + ex.Message,
8709 new KeyValuePair<string, object>(
"ContractId", ContractId),
8710 new KeyValuePair<string, object>(
"FileName", FileName),
8711 new KeyValuePair<string, object>(
"ContentType", ContentType),
8712 new KeyValuePair<string, object>(
"Size", Data.Length));
8716 ContentType, Data.Length);
8719 throw new IOException(
"Unable to upload attachment " + FileName +
" to broker.");
8721 await e2.
PUT(Data, ContentType, 10000);
8723 return await this.AddContractAttachmentAsyncPrivate(ContractId, e2.
GetUrl,
Signature);
8734 return this.GetAttachmentAsync(Url,
SignWith, 30000);
8746 using HttpClient HttpClient =
new HttpClient()
8748 Timeout = TimeSpan.FromMilliseconds(Timeout)
8750 HttpRequestMessage Request;
8751 HttpResponseMessage Response =
null;
8753 Request =
new HttpRequestMessage()
8755 RequestUri =
new Uri(Url),
8756 Method = HttpMethod.Get
8761 Response = await HttpClient.SendAsync(Request);
8763 if (Response.StatusCode ==
System.
Net.HttpStatusCode.Unauthorized &&
8764 !(Response.Headers.WwwAuthenticate is
null))
8766 foreach (AuthenticationHeaderValue Header
in Response.Headers.WwwAuthenticate)
8768 if (Header.Scheme ==
"NeuroFoundation.Sign")
8771 string Realm =
null;
8772 string NonceStr =
null;
8773 byte[] Nonce =
null;
8775 foreach (KeyValuePair<string, string> P
in Parameters)
8785 Nonce = Convert.FromBase64String(NonceStr);
8790 if (!
string.IsNullOrEmpty(Realm) && !
string.IsNullOrEmpty(NonceStr))
8793 StringBuilder sb =
new StringBuilder();
8795 sb.Append(
"jid=\"");
8796 sb.Append(this.client.FullJID);
8797 sb.Append(
"\", realm=\"");
8799 sb.Append(
"\", n=\"");
8800 sb.Append(NonceStr);
8801 sb.Append(
"\", s=\"");
8802 sb.Append(Convert.ToBase64String(
Signature));
8806 Request =
new HttpRequestMessage()
8808 RequestUri =
new Uri(Url),
8809 Method = HttpMethod.Get
8812 Request.Headers.Authorization =
new AuthenticationHeaderValue(Header.Scheme, sb.ToString());
8816 Response = await HttpClient.SendAsync(Request);
8823 if (!Response.IsSuccessStatusCode)
8825 ContentResponse Temp = await Content.Getters.WebGetter.ProcessResponse(Response, Request.RequestUri);
8829 string ContentType = Response.Content.Headers.ContentType.ToString();
8833 await Response.Content.CopyToAsync(File);
8835 catch (Exception ex)
8840 ExceptionDispatchInfo.Capture(ex).Throw();
8843 return new KeyValuePair<string, TemporaryFile>(ContentType, File);
8848 Response?.Dispose();
8860 StringBuilder Xml =
new StringBuilder();
8862 Xml.Append(
"<removeAttachment xmlns='");
8863 Xml.Append(NamespaceLegalIdentitiesCurrent);
8864 Xml.Append(
"' attachmentId='");
8868 return this.client.SendIqSet(this.componentAddress, Xml.ToString(), async (Sender, e) =>
8873 if (e.
Ok && !((E = e.FirstElement) is
null) && E.LocalName ==
"identity")
8888 TaskCompletionSource<LegalIdentity> Result =
new TaskCompletionSource<LegalIdentity>();
8890 await this.RemoveLegalIdAttachment(AttachmentId, (Sender, e) =>
8893 Result.TrySetResult(e.Identity);
8895 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to remove attachment."));
8897 return Task.CompletedTask;
8901 return await Result.Task;
8912 StringBuilder Xml =
new StringBuilder();
8914 Xml.Append(
"<removeAttachment xmlns='");
8915 Xml.Append(NamespaceSmartContractsCurrent);
8916 Xml.Append(
"' attachmentId='");
8920 return this.client.SendIqSet(this.componentAddress, Xml.ToString(), async (Sender, e) =>
8925 if (e.
Ok && !((E = e.FirstElement) is
null) && E.LocalName ==
"contract")
8927 ParsedContract Parsed = await Contract.Parse(E, this, false);
8931 Contract = Parsed.Contract;
8946 TaskCompletionSource<Contract> Result =
new TaskCompletionSource<Contract>();
8948 await this.RemoveContractAttachment(AttachmentId, (Sender, e) =>
8951 Result.TrySetResult(e.Contract);
8953 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to remove attachment."));
8955 return Task.CompletedTask;
8959 return await Result.Task;
8976 public (
byte[],
byte[]) Encrypt(
byte[] Message,
byte[] Nonce,
byte[] RecipientPublicKey,
string RecipientPublicKeyName)
8978 return this.Encrypt(Message, Nonce, RecipientPublicKey, RecipientPublicKeyName,
string.Empty);
8992 public (
byte[],
byte[]) Encrypt(
byte[] Message,
byte[] Nonce,
byte[] RecipientPublicKey,
string RecipientPublicKeyName,
8993 string RecipientPublicKeyNamespace)
8995 IE2eEndpoint LocalEndpoint = this.keys.FindLocalEndpoint(RecipientPublicKeyName, RecipientPublicKeyNamespace)
8996 ??
throw new NotSupportedException(
"Unable to find matching local key.");
9000 byte[] LocalPublicKey = LocalEndpoint.
PublicKey;
9002 SymmetricCipher, out
byte[] KeyCipherText);
9003 int KeyCipherTextLen = KeyCipherText is
null ? 0 : KeyCipherText.Length;
9006 byte[] Key =
new byte[16];
9007 byte[] IV =
new byte[16];
9012 for (i = 0; i < 32; i++)
9013 Digest[i] ^= NonceDigest[i];
9025 i = c + Message.Length;
9026 c = (i + 15) & ~0xf;
9028 ToEncrypt =
new byte[c];
9034 ToEncrypt[j] = (byte)(i & 127);
9037 ToEncrypt[j] |= 0x80;
9043 Buffer.BlockCopy(Message, 0, ToEncrypt, j, Message.Length);
9044 j += Message.Length;
9047 this.rnd.GetBytes(ToEncrypt, j, c - j);
9049 Buffer.BlockCopy(Digest, 0, Key, 0, 16);
9050 Buffer.BlockCopy(Digest, 16, IV, 0, 16);
9054 using ICryptoTransform Aes = this.aes.CreateEncryptor(Key, IV);
9055 Encrypted = Aes.TransformFinalBlock(ToEncrypt, 0, c);
9061 i = KeyCipherTextLen;
9070 c += KeyCipherTextLen + Encrypted.Length;
9072 byte[] Encrypted2 =
new byte[c];
9074 i = KeyCipherTextLen;
9079 Encrypted2[j] = (byte)(i & 127);
9082 Encrypted2[j] |= 0x80;
9088 Buffer.BlockCopy(KeyCipherText, 0, Encrypted2, j, KeyCipherTextLen);
9089 j += KeyCipherTextLen;
9091 Buffer.BlockCopy(Encrypted, 0, Encrypted2, j, Encrypted.Length);
9093 Encrypted = Encrypted2;
9095 else if (KeyCipherTextLen > 0)
9096 throw new InvalidOperationException(
"Shared secret ciphertexts not supported.");
9098 return (Encrypted, LocalPublicKey);
9112 IE2eEndpoint[] LocalEndpoints = this.keys?.FindCompatibleLocalEndpoints(SenderPublicKey) ?? Array.Empty<
IE2eEndpoint>();
9120 byte[] KeyCipherText;
9131 b = EncryptedMessage[i++];
9135 while ((b & 0x80) != 0);
9137 if (c < 0 || c > EncryptedMessage.Length - i)
9138 throw new InvalidOperationException(
"Unable to decrypt message.");
9140 KeyCipherText =
new byte[c];
9141 Buffer.BlockCopy(EncryptedMessage, 0, KeyCipherText, 0, c);
9144 KeyCipherText =
null;
9149 byte[] Key =
new byte[16];
9150 byte[] IV =
new byte[16];
9153 for (j = 0; j < 32; j++)
9154 Digest[j] ^= NonceDigest[j];
9156 Buffer.BlockCopy(Digest, 0, Key, 0, 16);
9157 Buffer.BlockCopy(Digest, 16, IV, 0, 16);
9161 using ICryptoTransform Aes = this.aes.CreateDecryptor(Key, IV);
9162 Decrypted = Aes.TransformFinalBlock(EncryptedMessage, i, EncryptedMessage.Length - i);
9173 while ((b & 0x80) != 0);
9175 if (c < 0 || c > Decrypted.Length - i)
9178 Exceptions.Add(
new InvalidOperationException(
"Unable to decrypt message."));
9182 byte[] Message =
new byte[c];
9184 Buffer.BlockCopy(Decrypted, i, Message, 0, c);
9188 catch (Exception ex)
9195 if (Exceptions is
null)
9196 throw new NotSupportedException(
"No compatible local key found.");
9197 else if (Exceptions.Count == 1)
9198 throw Exceptions.FirstItem;
9200 throw new AggregateException(Exceptions.ToArray());
9214 IE2eEndpoint LocalEndpoint = this.keys.FindLocalEndpoint(SenderPublicKey);
9216 byte[] KeyCipherText;
9227 b = EncryptedMessage[i++];
9231 while ((b & 0x80) != 0);
9233 if (c < 0 || c > EncryptedMessage.Length - i)
9234 throw new InvalidOperationException(
"Unable to decrypt message.");
9236 KeyCipherText =
new byte[c];
9237 Buffer.BlockCopy(EncryptedMessage, 0, KeyCipherText, 0, c);
9244 byte[] Key =
new byte[16];
9245 byte[] IV =
new byte[16];
9248 for (j = 0; j < 32; j++)
9249 Digest[j] ^= NonceDigest[j];
9251 Buffer.BlockCopy(Digest, 0, Key, 0, 16);
9252 Buffer.BlockCopy(Digest, 16, IV, 0, 16);
9256 using ICryptoTransform Aes = this.aes.CreateDecryptor(Key, IV);
9257 Decrypted = Aes.TransformFinalBlock(EncryptedMessage, i, EncryptedMessage.Length - i);
9268 while ((b & 0x80) != 0);
9270 if (c < 0 || c > Decrypted.Length - i)
9271 throw new InvalidOperationException(
"Unable to decrypt message.");
9273 byte[] Message =
new byte[c];
9275 Buffer.BlockCopy(Decrypted, i, Message, 0, c);
9282 #region Explicit authorization of access to Legal IDs
9292 public Task
AuthorizeAccessToId(
string LegalId,
string RemoteId,
bool Authorized, EventHandlerAsync<IqResultEventArgs> Callback,
object State)
9294 return this.AuthorizeAccessToId(this.GetTrustProvider(LegalId), LegalId, RemoteId, Authorized, Callback, State);
9306 public Task
AuthorizeAccessToId(
string Address,
string LegalId,
string RemoteId,
bool Authorized, EventHandlerAsync<IqResultEventArgs> Callback,
object State)
9308 StringBuilder Xml =
new StringBuilder();
9310 Xml.Append(
"<authorizeAccess xmlns='");
9311 Xml.Append(NamespaceLegalIdentitiesCurrent);
9312 Xml.Append(
"' id='");
9314 Xml.Append(
"' remoteId='");
9316 Xml.Append(
"' auth='");
9320 return this.client.SendIqSet(Address, Xml.ToString(), Callback, State);
9331 return this.AuthorizeAccessToIdAsync(this.GetTrustProvider(LegalId), LegalId, RemoteId, Authorized);
9343 TaskCompletionSource<bool> Result =
new TaskCompletionSource<bool>();
9345 await this.AuthorizeAccessToId(Address, LegalId, RemoteId, Authorized, (Sender, e) =>
9348 Result.TrySetResult(
true);
9350 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to authorize access to legal identity."));
9352 return Task.CompletedTask;
9361 #region Explicit authorization of access to Contracts
9371 public Task
AuthorizeAccessToContract(
string ContractId,
string RemoteId,
bool Authorized, EventHandlerAsync<IqResultEventArgs> Callback,
object State)
9373 return this.AuthorizeAccessToContract(this.GetTrustProvider(ContractId), ContractId, RemoteId, Authorized, Callback, State);
9385 public Task
AuthorizeAccessToContract(
string Address,
string ContractId,
string RemoteId,
bool Authorized, EventHandlerAsync<IqResultEventArgs> Callback,
object State)
9387 StringBuilder Xml =
new StringBuilder();
9389 Xml.Append(
"<authorizeAccess xmlns='");
9390 Xml.Append(NamespaceSmartContractsCurrent);
9391 Xml.Append(
"' id='");
9393 Xml.Append(
"' remoteId='");
9395 Xml.Append(
"' auth='");
9399 return this.client.SendIqSet(Address, Xml.ToString(), Callback, State);
9410 return this.AuthorizeAccessToContractAsync(this.GetTrustProvider(ContractId), ContractId, RemoteId, Authorized);
9422 TaskCompletionSource<bool> Result =
new TaskCompletionSource<bool>();
9424 await this.AuthorizeAccessToContract(Address, ContractId, RemoteId, Authorized, (Sender, e) =>
9427 Result.TrySetResult(
true);
9429 Result.TrySetException(e.
StanzaError ??
new Exception(
"Unable to authorize access to legal identity."));
9431 return Task.CompletedTask;
9440 #region Peer-review service providers
9449 return this.GetPeerReviewIdServiceProviders(this.componentAddress, Callback, State);
9461 StringBuilder Xml =
new StringBuilder();
9463 Xml.Append(
"<reviewIdProviders xmlns='");
9464 Xml.Append(NamespaceLegalIdentitiesCurrent);
9467 return this.client.SendIqGet(ComponentAddress, Xml.ToString(), async (Sender, e) =>
9469 List<ServiceProviderWithLegalId> Providers =
null;
9473 !((E = e.FirstElement) is
null) &&
9474 E.LocalName ==
"providers")
9476 Providers = new List<ServiceProviderWithLegalId>();
9478 foreach (XmlNode N in E.ChildNodes)
9480 if (N is XmlElement E2 && E2.LocalName ==
"provider")
9482 ServiceProviderWithLegalId Provider = this.ParseServiceProviderWithLegalId(E2);
9484 if (!(Provider is null))
9485 Providers.Add(Provider);
9502 string IconUrl =
null;
9503 string LegalId =
null;
9505 int IconHeight = -1;
9506 bool External =
false;
9508 foreach (XmlAttribute Attr
in Xml.Attributes)
9525 IconUrl = Attr.Value;
9529 if (!
int.TryParse(Attr.Value, out IconWidth))
9534 if (!
int.TryParse(Attr.Value, out IconHeight))
9539 LegalId = Attr.Value;
9549 if (Id is
null || Type is
null || Name is
null)
9552 if (
string.IsNullOrEmpty(IconUrl))
9556 if (IconWidth < 0 || IconHeight < 0)
9569 return this.GetPeerReviewIdServiceProvidersAsync(this.componentAddress);
9579 TaskCompletionSource<ServiceProviderWithLegalId[]> Providers =
new TaskCompletionSource<ServiceProviderWithLegalId[]>();
9581 await this.GetPeerReviewIdServiceProviders(ComponentAddress, (Sender, e) =>
9584 Providers.TrySetResult(e.ServiceProviders);
9586 Providers.TrySetException(e.
StanzaError ??
new Exception(
"Unable to get service providers."));
9588 return Task.CompletedTask;
9592 return await Providers.Task;
9597 #region Select Peer-review service
9608 public Task
SelectPeerReviewService(
string Provider,
string ServiceId, EventHandlerAsync<IqResultEventArgs> Callback,
object State)
9610 return this.SelectPeerReviewService(this.componentAddress, Provider, ServiceId, Callback, State);
9624 EventHandlerAsync<IqResultEventArgs> Callback,
object State)
9626 StringBuilder Xml =
new StringBuilder();
9628 Xml.Append(
"<selectReviewService xmlns='");
9629 Xml.Append(NamespaceLegalIdentitiesCurrent);
9630 Xml.Append(
"' provider='");
9632 Xml.Append(
"' serviceId='");
9636 return this.client.SendIqSet(ComponentAddress, Xml.ToString(), Callback, State);
9648 return this.SelectPeerReviewServiceAsync(this.componentAddress, Provider, ServiceId);
9661 TaskCompletionSource<bool> Providers =
new TaskCompletionSource<bool>();
9663 await this.SelectPeerReviewService(ComponentAddress, Provider, ServiceId, (Sender, e) =>
9666 Providers.TrySetResult(
true);
9668 Providers.TrySetException(e.
StanzaError ??
new Exception(
"Unable to select peer review service."));
9670 return Task.CompletedTask;
9674 await Providers.Task;
9679 #region Petition Client URL event
9681 private Task PetitionClientUrlEventHandler(
object Sender,
MessageEventArgs e)
Helps with parsing of commong data types.
static string Encode(bool x)
Encodes a Boolean for use in XML and other formats.
static KeyValuePair< string, string >[] ParseFieldValues(string Value)
Parses a set of comma or semicolon-separated field values, optionaly delimited by ' or " characters.
static bool TryParse(string s, out double Value)
Tries to decode a string encoded double.
Contains information about a response to a content request.
void AssertOk()
Asserts response is OK.
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
static string Encode(string s)
Encodes a string for use in XML.
static XmlWriterSettings WriterSettings(bool Indent, bool OmitXmlDeclaration)
Gets an XML writer settings object.
static XmlDocument ParseXml(string Xml)
Parses an XML Document from its string representation.
Static class managing loading of XSL resources stored as embedded resources or in content files.
static XmlSchema LoadSchema(string ResourceName)
Loads an XML schema from an embedded resource.
static void Validate(string ObjectID, XmlDocument Xml, params XmlSchema[] Schemas)
Validates an XML document given a set of XML schemas.
Static class managing the application event log. Applications and services log events on this static ...
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
static void Warning(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a warning event.
static void Notice(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a notice event.
static void Debug(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs a debug event.
static void Alert(string Message, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, string StackTrace, params KeyValuePair< string, object >[] Tags)
Logs an alert event.
This class handles incoming events from the XMPP network. The default behaviour is to log incoming ev...
static bool TryParse(string Value, string Type, out object ParsedValue)
Tries to parse a simple value.
Contains a reference to an attachment assigned to a legal object.
string LegalId
Legal ID of uploader of the attachment
string ContentType
Internet Content Type of binary attachment.
string Url
URL to retrieve attachment, if provided.
byte[] Signature
Binary signature of the attachment, generated by an approved legal identity of the account-holder....
Represents a digital signature on a contract.
Contains the definition of a contract
static Task< ParsedContract > Parse(XmlDocument Xml)
Validates a contract XML Document, and returns the contract definition in it.
byte[] ContentSchemaDigest
The hash digest of the schema used to validate the machine-readable contents (ForMachines) of the sma...
string ForMachinesLocalName
Local name used by the root node of the machine-readable contents of the contract (ForMachines).
Security.HashFunction ContentSchemaHashFunction
Hash function of the schema used to validate the machine-readable contents (ForMachines) of the smart...
void EncryptEncryptedParameters(string CreatorJid, IParameterEncryptionAlgorithm Algorithm)
Protects encrypted values, by encrypting the clear text string representations for those that lack en...
Parameter[] Parameters
Defined parameters for the smart contract.
DateTime? FirstSignatureAt
Timestamp of first client signature, if one exists.
ClientSignature[] ClientSignatures
Client signatures of the contract.
HumanReadableText[] ForHumans
Human-readable contents of the contract.
DateTime From
From when the contract is valid (if signed)
DateTime Updated
When the contract was last updated
async Task< bool > IsLegallyBinding(bool CheckCurrentTime, ContractsClient Client)
Checks if a contract is legally binding.
Attachment[] Attachments
Attachments assigned to the legal identity.
DateTime To
Until when the contract is valid (if signed)
string Provider
JID of the Trust Provider hosting the contract
bool HasTransientParameters
If contract has parameters that are transient.
XmlElement ForMachines
Machine-readable contents of the contract.
void Serialize(StringBuilder Xml, bool IncludeNamespace, bool IncludeIdAttribute, bool IncludeClientSignatures, bool IncludeAttachments, bool IncludeStatus, bool IncludeServerSignature, bool IncludeAttachmentReferences)
Serializes the Contract, in normalized form.
Role[] Roles
Roles defined in the smart contract.
ContractParts PartsMode
How parts are defined in the smart contract.
ContractState State
Contract state
string ContractId
Contract identity
string ForMachinesNamespace
Namespace used by the root node of the machine-readable contents of the contract (ForMachines).
ServerSignature ServerSignature
Server signature attesting to the validity of the contents of the contract.
bool HasEncryptedParameters
If contract has parameters that require encryption and decryption.
bool DecryptEncryptedParameters(string CreatorJid, IParameterEncryptionAlgorithm Algorithm)
Protects encrypted values, by encrypting the clear text string representations for those that lack en...
Contains a persisted shared secret associated with a smart contract.
bool HasSharedSecret
If a shared secret snapshot is available for the contract.
string CreatorJid
Bare JID of the contract creator.
SymmetricCipherAlgorithms KeyAlgorithm
Symmetric encryption algorithm used with the shared secret.
string ContractId
Contract ID.
byte[] SharedSecret
Shared secret snapshot stored with the contract state.
static void SetAllowedSources(ICallStackCheck[] ApprovedSources)
If access to sensitive properties is only accessible from a set of approved sources.
Adds support for legal identities, smart contracts and signatures to an XMPP client.
async Task ReadyForApprovalAsync(string Address, string LegalIdentityId)
Marks an Identity as Ready for Approval. Call this after necessary attachments have been added....
async Task PetitionIdentityAsync(string Address, string LegalId, string PetitionId, string Purpose, string ContextXml, string[] Properties, string[] Attachments)
Sends a petition to the owner of a legal identity, to access the information in the identity....
Task< bool > ImportKeys(string Xml)
Imports keys
Task GetServerPublicKey(DateTime? Timestamp, EventHandlerAsync< KeyEventArgs > Callback, object State)
Gets the server public key.
static Uri ContractIdUri(string ContractId)
Contract identity URI.
static EventHandlerAsync< PublicKeyEventArgs > GetLocalPublicKey
Event raised when a server public key is requested. Allows a local implementation to return a local k...
async Task DisableE2eEncryption()
Disables the use of the Contracts Client keys for End-to-End Encrypted communication over the XMPP cl...
Task Apply(Property[] Properties, bool Preview, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Applies for a legal identity to be registered.
Task DeleteContract(string Address, string ContractId, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Deletes a contract
Task< bool > ImportKeys(XmlDocument Xml)
Imports keys
async Task< bool > LoadKeys(bool CreateIfNone, ProfilerThread Thread)
Loads keys from the underlying persistence layer.
EventHandlerAsync< PetitionClientUrlEventArgs > PetitionClientUrlReceived
Event raised when a Client URL has been sent to the client as part of a petition process....
byte[] RandomBytes(int Nr)
Creates an array of random bytes.
async Task< LegalIdentity[]> GetContractLegalIdentitiesAsync(string Address, string ContractId, bool Current, bool Historic)
Gets available legal identities related to a contract.
Task CompromisedLegalIdentity(string LegalIdentityId, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Reports as Compromised one of the legal identities of the account, given its ID.
Task PetitionIdentityAsync(string Address, string LegalId, string PetitionId, string Purpose)
Sends a petition to the owner of a legal identity, to access the information in the identity....
Task GetContractLegalIdentities(string ContractId, EventHandlerAsync< LegalIdentitiesEventArgs > Callback, object State)
Gets available legal identities related to a contract.
Task< Contract > AddContractAttachmentAsync(string ContractId, string GetUrl, byte[] Signature)
Adds an attachment to a proposed or approved contract before it is being signed.
Task GetPeerReviewIdServiceProviders(EventHandlerAsync< ServiceProvidersEventArgs< ServiceProviderWithLegalId > > Callback, object State)
Gets available service providers who can help review an ID application.
Task Sign(Stream Data, SignWith SignWith, EventHandlerAsync< SignatureEventArgs > Callback, object State)
Signs binary data with the corresponding private key.
Task GetCreatedContractReferences(string Address, EventHandlerAsync< IdReferencesEventArgs > Callback, object State)
Get references to contracts the account has created.
Task PetitionSignatureResponseAsync(string LegalId, byte[] Content, byte[] Signature, string PetitionId, string RequestorFullJid, bool Response, string ContextXml)
Sends a response to a petition for a signature by the client. When a petition is received,...
async Task< Contract > DeleteContractAsync(string Address, string ContractId)
Deletes a contract
Task Validate(LegalIdentity Identity, bool ValidateState, EventHandlerAsync< IdentityValidationEventArgs > Callback, object State)
Validates a legal identity.
Task GetSignedContractReferences(EventHandlerAsync< IdReferencesEventArgs > Callback, object State)
Get references to contracts the account has signed.
Task< LegalIdentity > ApplyAsync(Property[] Properties, bool Preview)
Applies for a legal identity to be registered.
Task CreateContract(XmlElement ForMachines, HumanReadableText[] ForHumans, Role[] Roles, Part[] Parts, Parameter[] Parameters, ContractVisibility Visibility, ContractParts PartsMode, Duration? Duration, Duration? ArchiveRequired, Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore, bool CanActAsTemplate, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Creates a new contract.
async Task< string[]> GetCreatedContractReferencesAsync(string Address, int Offset, int MaxCount)
Get references to contracts the account has created.
async Task UpdateContract(string Address, Contract Contract, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Updates a contract
Task SendContractProposal(string ContractId, string Role, string To, string Message)
Sends a contract proposal to a recipient.
Task GetContractLegalIdentities(string Address, string ContractId, EventHandlerAsync< LegalIdentitiesEventArgs > Callback, object State)
Gets available legal identities related to a contract.
async Task GetTrustChain(string Domain, EventHandlerAsync< TrustChainEventArgs > Callback, object State)
Gets the trust chain from a domain. The trust chain is a list of domains, each one the parent of the ...
Task Validate(Contract Contract, EventHandlerAsync< ContractValidationEventArgs > Callback, object State)
Validates a smart contract.
async Task GenerateNewKeys()
Generates new keys for the contracts clients.
Task< ContractsEventArgs > GetCreatedContractsAsync(string Address)
Get contracts the account has created.
Task< LegalIdentity > AddLegalIdAttachmentAsync(string LegalId, string GetUrl, byte[] Signature)
Adds an attachment to a newly created legal identity.
Task GetSchema(string Namespace, SchemaDigest Digest, EventHandlerAsync< SchemaEventArgs > Callback, object State)
Gets a schema.
async Task< ContractsEventArgs > GetCreatedContractsAsync(string Address, int Offset, int MaxCount)
Get contracts the account has created.
async Task< LegalIdentity > RemoveLegalIdAttachmentAsync(string AttachmentId)
Removes an attachment from a newly created legal identity.
Task GetCreatedContracts(EventHandlerAsync< ContractsEventArgs > Callback, object State)
Get contracts the account has created.
Task< byte[]> GetSchemaAsync(string Address, string Namespace)
Gets a schema.
Task< LegalIdentity > ApplyAsync(Property[] Properties)
Applies for a legal identity to be registered.
Task PetitionContractResponseAsync(string Address, string ContractId, string PetitionId, string RequestorFullJid, bool Response)
Sends a response to a petition to access a smart contract. When a petition for a contract is received...
string KeySettingsPrefix
Prefix for client key runtime settings.
EventHandlerAsync< ClientMessageEventArgs > ClientMessage
Event raised when a Client Message has been received.
async Task Validate(LegalIdentity Identity, bool ValidateState, bool ValidateAttachments, EventHandlerAsync< IdentityValidationEventArgs > Callback, object State)
Validates a legal identity.
Task SelectPeerReviewServiceAsync(string Provider, string ServiceId)
Selects a service provider for peer review. This needs to be done before requesting the trust provide...
Task ObsoleteLegalIdentity(string Address, string LegalIdentityId, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Obsoletes one of the legal identities of the account, given its ID.
Task PetitionIdentityResponseAsync(string LegalId, string PetitionId, string RequestorFullJid, bool Response)
Sends a response to a petition for information about a legal identity. When a petition is received,...
Task< ContractValidationEventArgs > ValidateAsync(Contract Contract, bool ValidateState)
Validates a smart contract.
bool? ValidateSignature(LegalIdentity Identity, byte[] Data, byte[] Signature)
Validates a signature of binary data.
ulong RandomInteger(ulong MaxExclusive)
Creates a random long unsigned integer lower than MaxExclusive .
async Task GetServerPublicKey(string Address, DateTime? Timestamp, EventHandlerAsync< KeyEventArgs > Callback, object State)
Gets the server public key.
Task< KeyValuePair< string, TemporaryFile > > GetAttachmentAsync(string Url, SignWith SignWith)
Gets an attachment from a Trust Provider
Task PetitionSignatureAsync(string Address, string LegalId, byte[] Content, string PetitionId, string Purpose, string ContextXml, string[] Properties, string[] Attachments)
Sends a petition to a third party to request a digital signature of some content. The petition is not...
async Task ValidateSignature(string Address, string LegalId, byte[] Data, byte[] Signature, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Validates a signature of binary data.
Task GetSchema(string Namespace, EventHandlerAsync< SchemaEventArgs > Callback, object State)
Gets a schema.
async Task SignContract(string Address, Contract Contract, string Role, bool Transferable, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Signs a contract
Task SelectPeerReviewService(string ComponentAddress, string Provider, string ServiceId, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Selects a service provider for peer review. This needs to be done before requesting the trust provide...
Task< LegalIdentity > ObsoleteLegalIdentityAsync(string LegalIdentityId)
Obsoletes one of the legal identities of the account, given its ID.
ContractsClient(XmppClient Client, string ComponentAddress, ICallStackCheck[] ApprovedSources)
Adds support for legal identities, smart contracts and signatures to an XMPP client.
Task SendContractProposal(Contract Contract, string Role, string To)
Sends a contract proposal to a recipient. If the contract contains encrypted parameters,...
Task PetitionSignatureResponseAsync(string Address, string LegalId, byte[] Content, byte[] Signature, string PetitionId, string RequestorFullJid, bool Response)
Sends a response to a petition for a signature by the client. When a petition is received,...
Task< ServiceProviderWithLegalId[]> GetPeerReviewIdServiceProvidersAsync()
Gets available service providers who can help review an ID application.
Task< IdentityValidationEventArgs > ValidateAsync(LegalIdentity Identity, bool ValidateState)
Validates a legal identity.
Task Search(SearchFilter[] Filter, EventHandlerAsync< SearchResultEventArgs > Callback, object State)
Performs a search of public smart contracts.
Task ObsoleteLegalIdentity(string LegalIdentityId, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Obsoletes one of the legal identities of the account, given its ID.
SymmetricCipherAlgorithms PreferredEncryptionAlgorithm
Preferred Encryption Algorithm
Task Validate(LegalIdentity Identity, EventHandlerAsync< IdentityValidationEventArgs > Callback, object State)
Validates a legal identity.
Task PetitionSignatureAsync(string LegalId, byte[] Content, string PetitionId, string Purpose, string[] Properties, string[] Attachments)
Sends a petition to a third party to request a digital signature of some content. The petition is not...
ulong RandomInteger()
Creates a random long unsigned integer.
Task PetitionIdentityAsync(string LegalId, string PetitionId, string Purpose)
Sends a petition to the owner of a legal identity, to access the information in the identity....
const string NamespaceSmartContractsNeuroFoundationV1
urn:nf:iot:leg:sc:1.0
Task PetitionIdentityAsync(string Address, string LegalId, string PetitionId, string Purpose, string ContextXml)
Sends a petition to the owner of a legal identity, to access the information in the identity....
async Task< IdApplicationAttributesEventArgs > GetIdApplicationAttributesAsync()
Gets attributes relevant for application for legal identities on the broker.
Task< bool > LoadKeys(bool CreateIfNone)
Loads keys from the underlying persistence layer.
async Task< NetworkIdentity[]> GetContractNetworkIdentitiesAsync(string Address, string ContractId)
Gets available network identities related to a contract.
Task ReadyForApproval(string LegalIdentityId, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Marks an Identity as Ready for Approval. Call this after necessary attachments have been added....
const string NamespaceLegalIdentitiesIeeeV1
urn:ieee:iot:leg:id:1.0
Task< LegalIdentity > GetLegalIdentityAsync(string LegalIdentityId)
Gets legal identity registered with the account.
bool? ValidateSignature(LegalIdentity Identity, Stream Data, byte[] Signature)
Validates a signature of binary data.
Task PetitionSignatureAsync(string Address, string LegalId, byte[] Content, string PetitionId, string Purpose, string ContextXml)
Sends a petition to a third party to request a digital signature of some content. The petition is not...
Task< byte[]> GetSchemaAsync(string Namespace, SchemaDigest Digest)
Gets a schema.
Task< SearchResultEventArgs > SearchAsync(int Offset, int MaxCount, SearchFilter[] Filter)
Performs a search of public smart contracts.
Task CreateContract(string Address, string TemplateId, Part[] Parts, Parameter[] Parameters, ContractVisibility Visibility, ContractParts PartsMode, Duration? Duration, Duration? ArchiveRequired, Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore, bool CanActAsTemplate, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Creates a new contract from a template.
Task< ContractsEventArgs > GetCreatedContractsAsync()
Get contracts the account has created.
Task AuthorizeAccessToIdAsync(string LegalId, string RemoteId, bool Authorized)
Authorizes access to (or revokes access to) a Legal ID of the caller.
async Task PetitionSignatureResponseAsync(string Address, string LegalId, byte[] Content, byte[] Signature, string PetitionId, string RequestorFullJid, bool Response, string ContextXml)
Sends a response to a petition for a signature by the client. When a petition is received,...
async Task< LegalIdentity > CompromisedLegalIdentityAsync(string Address, string LegalIdentityId)
Reports as Compromised one of the legal identities of the account, given its ID.
Task PetitionSignatureResponseAsync(string LegalId, byte[] Content, byte[] Signature, string PetitionId, string RequestorFullJid, bool Response)
Sends a response to a petition for a signature by the client. When a petition is received,...
ContractsClient(XmppClient Client, string ComponentAddress, object[] ApprovedSources)
Adds support for legal identities, smart contracts and signatures to an XMPP client.
Task GetMatchingLocalKey(EventHandlerAsync< KeyEventArgs > Callback, object State)
Get the local key that matches the server key.
Task< SchemaReference[]> GetSchemasAsync()
Gets available schemas.
async Task< Contract > UploadContractAttachmentAsync(string ContractId, string FileName, Stream Data, string ContentType)
Uploads an attachment to a Smart Contract.
void SetAllowedSources(object[] ApprovedSources)
If access to sensitive methods is only accessible from a set of approved sources.
Task GetContracts(string Address, string[] ContractIds, EventHandlerAsync< ContractsEventArgs > Callback, object State)
Gets a collection of contracts
Task ObsoleteContract(string ContractId, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Obsoletes a contract
async Task< ContractsEventArgs > GetSignedContractsAsync(string Address, int Offset, int MaxCount)
Get contracts the account has signed.
Task GetSchema(string Address, string Namespace, EventHandlerAsync< SchemaEventArgs > Callback, object State)
Gets a schema.
Task GetLegalIdentities(string Address, EventHandlerAsync< LegalIdentitiesEventArgs > Callback, object State)
Gets legal identities registered with the account.
const string NamespaceLegalIdentitiesNeuroFoundationV1
urn:nf:iot:leg:id:1.0
async Task< ServiceProviderWithLegalId[]> GetPeerReviewIdServiceProvidersAsync(string ComponentAddress)
Gets available service providers who can help review an ID application.
Task< bool > HasPrivateKey(LegalIdentity Identity)
Checks if the private key of a legal identity is available. Private keys are required to be able to s...
Task DeleteContract(string ContractId, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Deletes a contract
Task GetCreatedContractReferences(int Offset, int MaxCount, EventHandlerAsync< IdReferencesEventArgs > Callback, object State)
Get references to contracts the account has created.
string ContractKeySettingsPrefix
Prefix for contract key runtime settings.
Task Search(string Address, SearchFilter[] Filter, EventHandlerAsync< SearchResultEventArgs > Callback, object State)
Performs a search of public smart contracts.
Task Search(string Address, int Offset, int MaxCount, SearchFilter[] Filter, EventHandlerAsync< SearchResultEventArgs > Callback, object State)
Performs a search of public smart contracts.
async Task< Contract > UploadContractAttachmentAsync(string ContractId, string FileName, byte[] Data, string ContentType)
Uploads an attachment to a Smart Contract.
Task Sign(byte[] Data, SignWith SignWith, EventHandlerAsync< SignatureEventArgs > Callback, object State)
Signs binary data with the corresponding private key.
Task PetitionContractAsync(string ContractId, string PetitionId, string Purpose)
Sends a petition to the parts of a smart contract, to access the information in the contract....
async Task GetSchema(string Address, string Namespace, SchemaDigest Digest, EventHandlerAsync< SchemaEventArgs > Callback, object State)
Gets a schema.
Task GetSignedContracts(string Address, int Offset, int MaxCount, EventHandlerAsync< ContractsEventArgs > Callback, object State)
Get contracts the account has signed.
Task AuthorizeAccessToId(string LegalId, string RemoteId, bool Authorized, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Authorizes access to (or revokes access to) a Legal ID of the caller.
DateTime KeysTimestamp
Timestamps of current keys used for signatures.
Task< LegalIdentity[]> GetContractLegalIdentitiesAsync(string Address, string ContractId)
Gets available legal identities related to a contract.
async Task< Contract > CreateContractAsync(string Address, string TemplateId, Part[] Parts, Parameter[] Parameters, ContractVisibility Visibility, ContractParts PartsMode, Duration? Duration, Duration? ArchiveRequired, Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore, bool CanActAsTemplate)
Creates a new contract from a template.
async Task PetitionIdentityResponseAsync(string Address, string LegalId, string PetitionId, string RequestorFullJid, bool Response, string ContextXml)
Sends a response to a petition for information about a legal identity. When a petition is received,...
bool IsE2eEncryptionEnabled
If End-to-End encryption is enabled.
Task CreateContract(string Address, XmlElement ForMachines, HumanReadableText[] ForHumans, Role[] Roles, Part[] Parts, Parameter[] Parameters, ContractVisibility Visibility, ContractParts PartsMode, Duration? Duration, Duration? ArchiveRequired, Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore, bool CanActAsTemplate, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Creates a new contract.
Task SignContract(Contract Contract, string Role, bool Transferable, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Signs a contract
Task GetCreatedContractReferences(string Address, int Offset, int MaxCount, EventHandlerAsync< IdReferencesEventArgs > Callback, object State)
Get references to contracts the account has created.
Task< string > GetLatestApprovedLegalId()
Gets the latest approved Legal ID.
async Task Validate(Contract Contract, bool ValidateState, bool ValidateAttachments, bool ValidateIdentities, bool ValidateIdentityAttachments, EventHandlerAsync< ContractValidationEventArgs > Callback, object State)
Validates a smart contract.
Task AddContractAttachment(string ContractId, string GetUrl, byte[] Signature, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Adds an attachment to a proposed or approved contract before it is being signed.
Task< LegalIdentity > CompromisedLegalIdentityAsync(string LegalIdentityId)
Reports as Compromised one of the legal identities of the account, given its ID.
const SymmetricCipherAlgorithms DefaultCipherAlgorithm
Default cipher name for encrypted parameters, if an algorithm is not explicitly defined.
Task GetContractNetworkIdentities(string Address, string ContractId, EventHandlerAsync< NetworkIdentitiesEventArgs > Callback, object State)
Gets available network identities related to a contract.
Task GetContractLegalIdentities(string ContractId, bool Current, bool Historic, EventHandlerAsync< LegalIdentitiesEventArgs > Callback, object State)
Gets available legal identities related to a contract.
Task SelectPeerReviewService(string Provider, string ServiceId, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Selects a service provider for peer review. This needs to be done before requesting the trust provide...
Task< Contract > GetContractAsync(string ContractId)
Gets a contract
Task< KeyValuePair< LegalIdentity, Exception > > ValidateSignatureAsyncEx(string LegalId, byte[] Data, byte[] Signature)
Validates a signature of binary data.
async Task CreateContract(string Address, string TemplateId, Part[] Parts, Parameter[] Parameters, ContractVisibility Visibility, ContractParts PartsMode, Duration? Duration, Duration? ArchiveRequired, Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore, bool CanActAsTemplate, IParameterEncryptionAlgorithm Algorithm, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Creates a new contract from a template.
Task AuthorizeAccessToId(string Address, string LegalId, string RemoteId, bool Authorized, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Authorizes access to (or revokes access to) a Legal ID of the caller.
async Task< IE2eEndpoint > GetMatchingLocalKeyAsync(string Address)
Get the local key that matches a given server key.
string GetTrustProvider(string EntityId)
Gets the trust provider hosting an entity with a given ID, in the form of LocalId@Provider.
Task< IdentityValidationEventArgs > ValidateAsync(LegalIdentity Identity)
Validates a legal identity.
async Task< Contract > CreateContractAsync(string Address, XmlElement ForMachines, HumanReadableText[] ForHumans, Role[] Roles, Part[] Parts, Parameter[] Parameters, ContractVisibility Visibility, ContractParts PartsMode, Duration? Duration, Duration? ArchiveRequired, Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore, bool CanActAsTemplate)
Creates a new contract.
Task< ContractValidationEventArgs > ValidateAsync(Contract Contract)
Validates a smart contract.
Task GetIdApplicationAttributes(EventHandlerAsync< IdApplicationAttributesEventArgs > Callback, object State)
Gets attributes relevant for application for legal identities on the broker.
Task PetitionPeerReviewIDAsync(string Address, string LegalId, LegalIdentity Identity, string PetitionId, string Purpose)
Sends a petition to a third party to peer review a new legal identity. The petition is not guaranteed...
async Task< byte[]> SignAsync(string Address, Stream Data, SignWith SignWith)
Signs binary data with the corresponding private key.
async Task ExportKeys(XmlWriter Output)
Exports Keys to XML.
async Task< LegalIdentity > UploadLegalIdAttachmentAsync(string LegalId, string FileName, Stream Data, string ContentType)
Uploads an attachment to a Legal Identity application.
Task PetitionContractAsync(string Address, string ContractId, string PetitionId, string Purpose)
Sends a petition to the parts of a smart contract, to access the information in the contract....
Task< NetworkIdentity[]> GetContractNetworkIdentitiesAsync(string ContractId)
Gets available network identities related to a contract.
Task< LegalIdentity[]> GetContractLegalIdentitiesAsync(string ContractId, bool Current, bool Historic)
Gets available legal identities related to a contract.
async Task< Contract > GetContractAsync(string Address, string ContractId)
Gets a contract
async Task< bool > ImportKeys(XmlElement Xml)
Imports keys
async Task PetitionContractAsync(string Address, string ContractId, string PetitionId, string Purpose, string ContextXml)
Sends a petition to the parts of a smart contract, to access the information in the contract....
Task< IE2eEndpoint > GetServerPublicKeyAsync()
Gets the server public key.
async Task< Contract > ObsoleteContractAsync(string Address, string ContractId)
Obsoletes a contract
Task GetContract(string Address, string ContractId, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Gets a contract
async Task< LegalIdentity[]> GetLegalIdentitiesAsync(string Address)
Gets legal identities registered with the account.
async Task< ContractsEventArgs > GetContractsAsync(string[] ContractIds)
Gets a collection of contracts
Task< byte[]> SignAsync(byte[] Data, SignWith SignWith)
Signs binary data with the corresponding private key.
ContractsClient(XmppClient Client, string ComponentAddress)
Adds support for legal identities, smart contracts and signatures to an XMPP client.
async Task PetitionContractResponseAsync(string Address, string ContractId, string PetitionId, string RequestorFullJid, bool Response, string ContextXml)
Sends a response to a petition to access a smart contract. When a petition for a contract is received...
Task GetSchemas(EventHandlerAsync< SchemaReferencesEventArgs > Callback, object State)
Gets available schemas.
async Task SendContractProposal(Contract Contract, string Role, string To, string Message)
Sends a contract proposal to a recipient. If the contract contains encrypted parameters,...
byte[] DecryptSentMessage(byte[] EncryptedMessage, byte[] SenderPublicKey, byte[] Nonce)
Decrypts a message that was sent by the client using the current keys.
static string ContractIdUriString(string ContractId)
Contract identity URI, as a string.
async Task< KeyValuePair< LegalIdentity, Exception > > ValidateSignatureAsyncEx(string Address, string LegalId, byte[] Data, byte[] Signature)
Validates a signature of binary data.
Task PetitionIdentityAsync(string Address, string LegalId, string PetitionId, string Purpose, string[] Properties, string[] Attachments)
Sends a petition to the owner of a legal identity, to access the information in the identity....
Task< string[]> GetSignedContractReferencesAsync(int Offset, int MaxCount)
Get references to contracts the account has signed.
Task GetSignedContracts(string Address, EventHandlerAsync< ContractsEventArgs > Callback, object State)
Get contracts the account has signed.
const string NamespaceOnboarding
http://waher.se/schema/Onboarding/v1.xsd
async Task SelectPeerReviewServiceAsync(string ComponentAddress, string Provider, string ServiceId)
Selects a service provider for peer review. This needs to be done before requesting the trust provide...
static readonly string[] NamespacesSmartContracts
Namespaces supported for smart contracts.
Task GetCreatedContracts(string Address, int Offset, int MaxCount, EventHandlerAsync< ContractsEventArgs > Callback, object State)
Get contracts the account has created.
async Task AuthorizeAccessToContractAsync(string Address, string ContractId, string RemoteId, bool Authorized)
Authorizes access to (or revokes access to) a Contract of which the caller is part and can access.
byte[] DecryptReceivedMessage(byte[] EncryptedMessage, byte[] SenderPublicKey, byte[] Nonce)
Decrypts a message that was aimed at the client using the current keys.
Task PetitionContractResponseAsync(string ContractId, string PetitionId, string RequestorFullJid, bool Response)
Sends a response to a petition to access a smart contract. When a petition for a contract is received...
Task AuthorizeAccessToContract(string Address, string ContractId, string RemoteId, bool Authorized, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Authorizes access to (or revokes access to) a Contract of which the caller is part and can access.
Task GetTrustChain(EventHandlerAsync< TrustChainEventArgs > Callback, object State)
Gets the trust chain from the current domain. The trust chain is a list of domains,...
Task ReadyForApprovalAsync(string LegalIdentityId)
Marks an Identity as Ready for Approval. Call this after necessary attachments have been added....
async Task< LegalIdentity > AddPeerReviewIDAttachment(LegalIdentity Identity, LegalIdentity ReviewerLegalIdentity, byte[] PeerSignature)
Adds an attachment to a legal identity with information about a peer review of the identity.
async Task< KeyValuePair< string, TemporaryFile > > GetAttachmentAsync(string Url, SignWith SignWith, int Timeout)
Gets an attachment from a Trust Provider
Task< Contract > UpdateContractAsync(Contract Contract)
Updates a contract
Task< LegalIdentity[]> GetLegalIdentitiesAsync()
Gets legal identities registered with the account.
async Task< string > ExportKeys()
Exports Keys to XML.
Task PetitionSignatureAsync(string Address, string LegalId, byte[] Content, string PetitionId, string Purpose, string[] Properties, string[] Attachments)
Sends a petition to a third party to request a digital signature of some content. The petition is not...
Task GetLegalIdentity(string Address, string LegalIdentityId, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Gets information about a legal identity given its ID.
Task< Contract > SignContractAsync(Contract Contract, string Role, bool Transferable)
Signs a contract
Task GetContract(string ContractId, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Gets a contract
async Task< Contract > RemoveContractAttachmentAsync(string AttachmentId)
Removes an attachment from a proposed or approved contract before it is being signed.
Task UpdateContract(Contract Contract, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Updates a contract
async Task AuthorizeAccessToIdAsync(string Address, string LegalId, string RemoteId, bool Authorized)
Authorizes access to (or revokes access to) a Legal ID of the caller.
Task AuthorizeAccessToContract(string ContractId, string RemoteId, bool Authorized, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Authorizes access to (or revokes access to) a Contract of which the caller is part and can access.
const string E2eKeySemaphoreName
Name of semaphore used to synchronize access to End-to-End Encryption keys used for legal identities ...
Task< SearchResultEventArgs > SearchAsync(SearchFilter[] Filter)
Performs a search of public smart contracts.
Task PetitionIdentityResponseAsync(string LegalId, string PetitionId, string RequestorFullJid, bool Response, string ContextXml)
Sends a response to a petition for information about a legal identity. When a petition is received,...
Task< LegalIdentity[]> GetContractLegalIdentitiesAsync(string ContractId)
Gets available legal identities related to a contract.
override void Dispose()
Disposes of the extension.
async Task Apply(string Address, Property[] Properties, bool Preview, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Applies for a legal identity to be registered.
Task RemoveContractAttachment(string AttachmentId, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Removes an attachment from a proposed or approved contract before it is being signed.
Task GetSchemas(string Address, EventHandlerAsync< SchemaReferencesEventArgs > Callback, object State)
Gets available schemas.
async Task< SearchResultEventArgs > SearchAsync(string Address, int Offset, int MaxCount, SearchFilter[] Filter)
Performs a search of public smart contracts.
Task< IE2eEndpoint > GetMatchingLocalKeyAsync()
Get the local key that matches the server key.
EventHandlerAsync< IdentityReviewEventArgs > IdentityReview
Event raised when an Identity Application has been automatically reviewed.
Task< LegalIdentity > ValidateSignatureAsync(string LegalId, byte[] Data, byte[] Signature)
Validates a signature of binary data.
async Task< byte[]> SignAsync(string Address, byte[] Data, SignWith SignWith)
Signs binary data with the corresponding private key.
Task< string[]> GetSignedContractReferencesAsync()
Get references to contracts the account has signed.
Task AddLegalIdAttachment(string LegalId, string GetUrl, byte[] Signature, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Adds an attachment to a newly created legal identity.
static bool IsNamespaceSmartContract(string Namespace)
If a namespace corresponds to a smart contract namespace.
async Task CreateContract(string Address, XmlElement ForMachines, HumanReadableText[] ForHumans, Role[] Roles, Part[] Parts, Parameter[] Parameters, ContractVisibility Visibility, ContractParts PartsMode, Duration? Duration, Duration? ArchiveRequired, Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore, bool CanActAsTemplate, IParameterEncryptionAlgorithm Algorithm, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Creates a new contract.
async Task Sign(string Address, byte[] Data, SignWith SignWith, EventHandlerAsync< SignatureEventArgs > Callback, object State)
Signs binary data with the corresponding private key.
int RandomInteger(int MinInclusive, int MaxInclusive)
Creates a random number in a range.
Task Validate(Contract Contract, bool ValidateState, EventHandlerAsync< ContractValidationEventArgs > Callback, object State)
Validates a smart contract.
Task PetitionSignatureAsync(string LegalId, byte[] Content, string PetitionId, string Purpose)
Sends a petition to a third party to request a digital signature of some content. The petition is not...
Task< SearchResultEventArgs > SearchAsync(string Address, SearchFilter[] Filter)
Performs a search of public smart contracts.
Task RemoveLegalIdAttachment(string AttachmentId, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Removes an attachment from a newly created legal identity.
Task Search(int Offset, int MaxCount, SearchFilter[] Filter, EventHandlerAsync< SearchResultEventArgs > Callback, object State)
Performs a search of public smart contracts.
Task CreateContract(string TemplateId, Part[] Parts, Parameter[] Parameters, ContractVisibility Visibility, ContractParts PartsMode, Duration? Duration, Duration? ArchiveRequired, Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore, bool CanActAsTemplate, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Creates a new contract from a template.
Task GetCreatedContracts(int Offset, int MaxCount, EventHandlerAsync< ContractsEventArgs > Callback, object State)
Get contracts the account has created.
Task< string[]> GetTrustChainAsync()
Gets the trust chain from the current domain. The trust chain is a list of domains,...
Task PetitionPeerReviewIDAsync(string LegalId, LegalIdentity Identity, string PetitionId, string Purpose)
Sends a petition to a third party to peer review a new legal identity. The petition is not guaranteed...
Task GetSignedContractReferences(string Address, int Offset, int MaxCount, EventHandlerAsync< IdReferencesEventArgs > Callback, object State)
Get references to contracts the account has signed.
Task GetLegalIdentities(EventHandlerAsync< LegalIdentitiesEventArgs > Callback, object State)
Gets legal identities registered with the account.
Task< string[]> GetCreatedContractReferencesAsync(string Address)
Get references to contracts the account has created.
async Task< LegalIdentity > ObsoleteLegalIdentityAsync(string Address, string LegalIdentityId)
Obsoletes one of the legal identities of the account, given its ID.
async Task GetContracts(string[] ContractIds, EventHandlerAsync< ContractsEventArgs > Callback, object State)
Gets a collection of contracts
Task GetSignedContracts(EventHandlerAsync< ContractsEventArgs > Callback, object State)
Get contracts the account has signed.
Task ValidateSignature(string LegalId, byte[] Data, byte[] Signature, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Validates a signature of binary data.
Task PetitionIdentityAsync(string LegalId, string PetitionId, string Purpose, string[] Properties, string[] Attachments)
Sends a petition to the owner of a legal identity, to access the information in the identity....
Task GetPeerReviewIdServiceProviders(string ComponentAddress, EventHandlerAsync< ServiceProvidersEventArgs< ServiceProviderWithLegalId > > Callback, object State)
Gets available service providers who can help review an ID application.
static bool IsNamespaceLegalIdentity(string Namespace)
If a namespace corresponds to a legal identity namespace.
async Task EnableE2eEncryption()
Enables the keys of the Contracts Client to be used for End-to-End Encrypted communication over the X...
Task< Contract > CreateContractAsync(XmlElement ForMachines, HumanReadableText[] ForHumans, Role[] Roles, Part[] Parts, Parameter[] Parameters, ContractVisibility Visibility, ContractParts PartsMode, Duration? Duration, Duration? ArchiveRequired, Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore, bool CanActAsTemplate)
Creates a new contract.
override string[] Extensions
Implemented extensions.
Task SendContractProposal(string ContractId, string Role, string To)
Sends a contract proposal to a recipient.
Task< Contract > DeleteContractAsync(string ContractId)
Deletes a contract
async Task< bool > CanSignAs(CaseInsensitiveString ReferenceId, CaseInsensitiveString SignatoryId)
Checks if an identity can sign for another reference identity (i.e. the old might have been obsoleted...
async Task< Contract > SignContractAsync(string Address, Contract Contract, string Role, bool Transferable)
Signs a contract
Task GetLegalIdentity(string LegalIdentityId, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Gets information about a legal identity given its ID.
Task< ContractsEventArgs > GetSignedContractsAsync(int Offset, int MaxCount)
Get contracts the account has signed.
Task< byte[]> SignAsync(Stream Data, SignWith SignWith)
Signs binary data with the corresponding private key.
Task PetitionContractResponseAsync(string ContractId, string PetitionId, string RequestorFullJid, bool Response, string ContextXml)
Sends a response to a petition to access a smart contract. When a petition for a contract is received...
Task GetServerPublicKey(EventHandlerAsync< KeyEventArgs > Callback, object State)
Gets the server public key.
async Task< bool > HasPrivateKey(string IdentityId)
Checks if the private key of a legal identity is available. Private keys are required to be able to s...
async Task< IE2eEndpoint > GetServerPublicKeyAsync(string Address)
Gets the server public key.
Task< string[]> GetCreatedContractReferencesAsync(int Offset, int MaxCount)
Get references to contracts the account has created.
Task< string[]> GetCreatedContractReferencesAsync()
Get references to contracts the account has created.
void SetPreferredEncryptionAlgorithm(SymmetricCipherAlgorithms Algorithm, bool Lock)
Sets the preferred encryption algorithm.
Task Apply(string Address, Property[] Properties, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Applies for a legal identity to be registered.
Task< ContractsEventArgs > GetSignedContractsAsync()
Get contracts the account has signed.
async Task< ContractValidationEventArgs > ValidateAsync(Contract Contract, bool ValidateState, bool ValidateAttachments, bool ValidateIdentities, bool ValidateIdentityAttachments)
Validates a smart contract.
async Task Sign(string Address, Stream Data, SignWith SignWith, EventHandlerAsync< SignatureEventArgs > Callback, object State)
Signs binary data with the corresponding private key.
async Task< LegalIdentity > UploadLegalIdAttachmentAsync(string LegalId, string FileName, byte[] Data, string ContentType)
Uploads an attachment to a Legal Identity application.
async Task< IdentityValidationEventArgs > ValidateAsync(LegalIdentity Identity, bool ValidateState, bool ValidateAttachments)
Validates a legal identity.
async Task< string[]> GetTrustChainAsync(string Domain)
Gets the trust chain from a domain. The trust chain is a list of domains, each one the parent of the ...
async Task< string > GetLatestApprovedLegalId(byte[] PublicKey)
Gets the (latest) approved Legal ID whose public key matches PublicKey .
async Task< LegalIdentity > ValidateSignatureAsync(string Address, string LegalId, byte[] Data, byte[] Signature)
Validates a signature of binary data.
Task Apply(Property[] Properties, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Applies for a legal identity to be registered.
async Task< Contract > UpdateContractAsync(string Address, Contract Contract)
Updates a contract
void SetAllowedSources(ICallStackCheck[] ApprovedSources)
If access to sensitive methods is only accessible from a set of approved sources.
Task ReadyForApproval(string Address, string LegalIdentityId, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Marks an Identity as Ready for Approval. Call this after necessary attachments have been added....
Task AuthorizeAccessToContractAsync(string ContractId, string RemoteId, bool Authorized)
Authorizes access to (or revokes access to) a Contract of which the caller is part and can access.
Task GetSignedContracts(int Offset, int MaxCount, EventHandlerAsync< ContractsEventArgs > Callback, object State)
Get contracts the account has signed.
Task GetSignedContractReferences(string Address, EventHandlerAsync< IdReferencesEventArgs > Callback, object State)
Get references to contracts the account has signed.
const string NamespaceSmartContractsCurrent
Current namespce for smart contracts.
Task< Contract > CreateContractAsync(string TemplateId, Part[] Parts, Parameter[] Parameters, ContractVisibility Visibility, ContractParts PartsMode, Duration? Duration, Duration? ArchiveRequired, Duration? ArchiveOptional, DateTime? SignAfter, DateTime? SignBefore, bool CanActAsTemplate)
Creates a new contract from a template.
Task< byte[]> GetSchemaAsync(string Namespace)
Gets a schema.
const string NamespaceSmartContractsIeeeV1
urn:ieee:iot:leg:sc:1.0
async Task< LegalIdentity > GetLegalIdentityAsync(string Address, string LegalIdentityId)
Gets legal identity registered with the account.
static void ParseValidationDetails(XmlElement Content, IdentityReviewEventArgs e)
Parses identity review details from an Identity Review message, and fills the corresponding propertie...
static string LegalIdUriString(string LegalId)
Legal identity URI, as a string.
async Task< LegalIdentity > ApplyAsync(string Address, Property[] Properties, bool Preview)
Applies for a legal identity to be registered.
Task ObsoleteContract(string Address, string ContractId, EventHandlerAsync< SmartContractEventArgs > Callback, object State)
Obsoletes a contract
Task CompromisedLegalIdentity(string Address, string LegalIdentityId, EventHandlerAsync< LegalIdentityEventArgs > Callback, object State)
Reports as Compromised one of the legal identities of the account, given its ID.
void SetKeySettingsInstance(string InstanceName, bool Locked)
Sets the key settings instance name.
Task< Contract > ObsoleteContractAsync(string ContractId)
Obsoletes a contract
Task GetCreatedContractReferences(EventHandlerAsync< IdReferencesEventArgs > Callback, object State)
Get references to contracts the account has created.
Task< ContractsEventArgs > GetCreatedContractsAsync(int Offset, int MaxCount)
Get contracts the account has created.
static readonly string[] NamespacesLegalIdentities
Namespaces supported for legal identities.
async Task< ContractsEventArgs > GetContractsAsync(string Address, string[] ContractIds)
Gets a collection of contracts
const string NamespaceLegalIdentitiesCurrent
Current namespace for legal identities.
async Task SendContractProposal(string ContractId, string Role, string To, string Message, byte[] Key, SymmetricCipherAlgorithms KeyAlgorithm)
Sends a contract proposal to a recipient.
string ComponentAddress
Component address.
async Task GetMatchingLocalKey(string Address, EventHandlerAsync< KeyEventArgs > Callback, object State)
Get the local key that matches a given server key.
async Task< string[]> GetSignedContractReferencesAsync(string Address, int Offset, int MaxCount)
Get references to contracts the account has signed.
static Uri LegalIdUri(string LegalId)
Legal identity URI.
Task PetitionIdentityResponseAsync(string Address, string LegalId, string PetitionId, string RequestorFullJid, bool Response)
Sends a response to a petition for information about a legal identity. When a petition is received,...
async Task< byte[]> GetSchemaAsync(string Address, string Namespace, SchemaDigest Digest)
Gets a schema.
Task PetitionSignatureAsync(string Address, string LegalId, byte[] Content, string PetitionId, string Purpose)
Sends a petition to a third party to request a digital signature of some content. The petition is not...
Task GetCreatedContracts(string Address, EventHandlerAsync< ContractsEventArgs > Callback, object State)
Get contracts the account has created.
Task GetContractLegalIdentities(string Address, string ContractId, bool Current, bool Historic, EventHandlerAsync< LegalIdentitiesEventArgs > Callback, object State)
Gets available legal identities related to a contract.
Task< LegalIdentity > ApplyAsync(string Address, Property[] Properties)
Applies for a legal identity to be registered.
async Task< SchemaReference[]> GetSchemasAsync(string Address)
Gets available schemas.
Task GetServerPublicKey(string Address, EventHandlerAsync< KeyEventArgs > Callback, object State)
Gets the server public key.
Task GetContractNetworkIdentities(string ContractId, EventHandlerAsync< NetworkIdentitiesEventArgs > Callback, object State)
Gets available network identities related to a contract.
Identity Review event arguments.
Event arguments for smart contract petitions
Event arguments for smart contract petition responses
Event arguments for smart contract proposals
Event arguments for events referencing a contract.
Event arguments for contract signature events
Event arguments for identity validation responses
Event arguments for Contracts responses
Event arguments for callback methods to ID Application attributes queries.
Event arguments for ID References responses
Identity Review event arguments.
bool? IsValid
If the application has been validated (true), invalidated (false), or not yet validated (null).
bool HasValidatedPhotos
If the application has validated photos.
bool HasValidatedClaims
If the application has validated claims.
string LegalId
Identifier of associated Legal ID.
Event arguments for identity validation responses
KeyValuePair< string, object >[] Tags
Associated tags with more information.
IdentityStatus Status
Validation status of legal identity.
Event arguments for key responses
Event arguments for legal identities responses
Event arguments for legal identity responses
Event arguments for legal identity petitions
Event arguments for legal identity petition responses
Event arguments for network identities responses
Event arguments for events where a client URL needs to be displayed when performing a petition.
Event arguments for public key request events.
IE2eEndpoint Key
Public key of endpoint corresponding to Address.
DateTime? ValidTo
To when key is valid, in UTC.
DateTime? ValidFrom
From when key is valid, in UTC.
Event arguments for schema responses
Event arguments for Schema Reference events.
byte[] XmlSchema
XML Schema definition, if available.
Event arguments for Schema References responses
Event arguments for Search Result responses
Event arguments for Service Provider callback methods.
Event arguments for signature responses
Event arguments for digital signature petitions
Event arguments for signature petition responses
Event arguments for smart contract responses
Event arguments for Service Provider callback methods.
Event arguments for signature validation events.
bool? Valid
If signature is valid (true), invalid (false), or if signature validation was not performed (null).
LegalIdentity Identity
Legal Identity associated with the LegalId
override async Task< HumanReadableElement > IsWellDefined()
Checks if the element is well-defined.
Class representing human-readable text.
Represents an invalidated claim.
Represents an invalidated photo.
string Namespace
Namespace used when serializing the identity for signatures.
DateTime From
From what point in time the legal identity is valid.
DateTime Updated
When the identity object was last updated
DateTime To
To what point in time the legal identity is valid.
DateTime Created
When the identity object was created
IdentityState State
Current state of identity
byte[] ClientSignature
Client signature
string ClientKeyName
Type of key used for client signatures
string Provider
Provider where the identity is maintained.
byte[] ClientPubKey
Client Public key
byte[] ServerSignature
Server signature
string Id
ID of the legal identity
void Serialize(StringBuilder Xml, bool IncludeNamespace, bool IncludeIdAttribute, bool IncludeClientSignature, bool IncludeAttachments, bool IncludeStatus, bool IncludeServerSignature, bool IncludeAttachmentReferences)
Serializes the identity to XML
static LegalIdentity Parse(string Xml)
Parses an identity from its XML representation
Attachment[] Attachments
Attachments assigned to the legal identity.
Contains information about a legal identity generated by the client.
bool HasPrivateKey
If a private key snapshot is available for the legal identity.
DateTime Timestamp
Timestamp when the legal identity was created or last updated.
string KeyNamespace
Namespace of key algorithm used when the identity was created.
string KeyName
Name of key algorithm used when the identity was created.
IdentityState State
State of the legal identity.
CaseInsensitiveString LegalId
Identity string assigned to the legal identity.
static void SetAllowedSources(ICallStackCheck[] ApprovedSources)
If access to sensitive properties is only accessible from a set of approved sources.
byte[] PublicKey
Public Key used by the cryptographic algororithm used to sign the identity application.
byte[] PrivateKey
Private key snapshot stored with the legal identity.
HumanReadableText[] Descriptions
Discriptions of the object, in different languages.
Contains a network identity related to a legal identity
Implements parameter encryption using symmetric ciphers avaialble through IE2eSymmetricCipher in the ...
static Task< ParameterEncryptionAlgorithm > Create(SymmetricCipherAlgorithms Algorithm, ContractsClient Client)
Implements parameter encryption using symmetric ciphers avaialble through IE2eSymmetricCipher in the ...
Abstract base class for contractual parameters
abstract void Populate(Variables Variables)
Populates a variable collection with the value of the parameter.
string ErrorText
After IsParameterValid(Variables) or IsParameterValid(Variables, ContractsClient) has been execited,...
abstract string StringValue
String representation of value.
Task< bool > IsParameterValid(Variables Variables)
Checks if the parameter value is valid.
string Name
Parameter name
byte[] ProtectedValue
Protected value, in case Protection is not equal to ProtectionLevel.Normal.
abstract string ParameterType
Parameter type name, corresponding to the local name of the parameter element in XML.
abstract object ObjectValue
Parameter value.
ParameterErrorReason? ErrorReason
After IsParameterValid(Variables) or IsParameterValid(Variables, ContractsClient) has been execited,...
void Serialize(StringBuilder Xml)
Serializes the parameter, in normalized form.
ProtectionLevel Protection
Level of confidentiality of the information provided by the parameter.
Contains information about a parsed contract.
Contract Contract
Contract object
Class defining a part in a contract
string LegalId
Legal identity of part
string Role
Role of the part in the contract
Represents a potential claim.
Contains a list of public key records for an endpoint.
HashFunction Function
Hash Function used to calculate the digest.
byte[] Digest
Hash Digest of schema file
References a XML Schema used for validating machine-readable contents in smart contracts.
Abstract base class for Smart Contract Search filters.
Contains information about a service provider with a legal identity.
Abstract base class of signatures
byte[] DigitalSignature
Digital Signature
DateTime Timestamp
Timestamp of signature.
Represents a validated claim.
Represents a validated photo.
Contains information about a validation error.
Event arguments for responses to IQ queries.
bool Ok
If the response is an OK result response (true), or an error response (false).
object State
State object passed to the original request.
XmppException StanzaError
Any stanza error returned.
string ErrorText
Any error specific text.
XmlElement FirstElement
First child element of the Response element.
Event arguments for message events.
string Id
ID attribute of message stanza.
string From
From where the message was received.
XmlElement Message
The message stanza.
string FromBareJID
Bare JID of resource sending the message.
string ErrorText
Any error specific text.
bool Ok
If the response is an OK result response (true), or an error response (false).
string To
To whom the message was sent.
bool UsesE2eEncryption
If end-to-end encryption was used in the request.
XmlElement Content
Content of the message. For messages that are processed by registered message handlers,...
XmppException StanzaError
Any stanza error returned.
Class managing HTTP File uploads, as defined in XEP-0363.
async Task PrepareFileUpload(string FileName, string ContentType, long FileSize, FilePurpose Purpose)
Prepares a file upload, by letting the broker know that a file will be uploaded, and for what purpose...
Task< HttpFileUploadEventArgs > RequestUploadSlotAsync(string FileName, string ContentType, long ContentSize)
Uploads a file to the upload component.
string FileUploadJid
JID of HTTP File Upload component.
Event arguments for HTTP File Upload callback methods.
Task PUT(byte[] Content, string ContentType, int Timeout)
Uploads file content to the server.
Abstract base class for Elliptic Curve endpoints.
EllipticCurve Curve
Elliptic Curve
Abstract base class for Module Lattice endpoints.
byte[] ExportPrivateKey()
Exports the private key (seed) of the endpoint.
RSA / AES-256 hybrid cipher.
byte[] Export(bool Private)
Exports information from the encryption object.
override bool Verify(byte[] Data, byte[] Signature)
Verifies a signature.
Class managing end-to-end encryption.
static bool TryCreateEndpoint(string LocalName, string Namespace, out IE2eEndpoint Endpoint)
Tries to create a new endpoint, given its qualified name.
IE2eEndpoint FindLocalEndpoint(IE2eEndpoint RemoteEndpoint)
Returns the local endpoint that matches a given remote endpoint.
static bool TryGetEndpoint(string LocalName, string Namespace, out IE2eEndpoint Endpoint)
Tries to get an existing endpoint, given its qualified name.
static bool IsE2eEncryptionEnabled(XmppClient Client)
If End-to-End encryption is enabled on an XMPP client.
static IE2eEndpoint[] CreateEndpoints(int DesiredSecurityStrength, int MinSecurityStrength, int MaxSecurityStrength)
Creates a set of endpoints within a range of security strengths.
static bool TryGetEndpointSecurity(XmppClient Client, out EndpointSecurity EndpointSecurity)
Tries to get a registered endpoint security manager from an XMPP client.
Implements support for the AES-256 cipher in hybrid End-to-End encryption schemes.
Maintains information about an item in the roster.
string LastPresenceFullJid
Full JID of last resource sending online presence.
The addressed JID or item requested cannot be found; the associated error type SHOULD be "cancel".
The intended recipient is temporarily unavailable, undergoing maintenance, etc.; the associated error...
Manages an XMPP client connection. Implements XMPP, as defined in https://tools.ietf....
bool UnregisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync< MessageEventArgs > Handler, bool RemoveNamespaceAsClientFeature)
Unregisters a Message handler.
static string GetDomain(string JID)
Gets the domain part of a JID.
static string GetBareJID(string JID)
Gets the Bare JID from a JID, which may be a Full JID.
void RegisterMessageHandler(string LocalName, string Namespace, EventHandlerAsync< MessageEventArgs > Handler, bool PublishNamespaceAsClientFeature)
Registers a Message handler.
Task< uint > SendIqGet(string To, string Xml, EventHandlerAsync< IqResultEventArgs > Callback, object State)
Sends an IQ Get request.
Base class for XMPP Extensions.
XmppClient client
XMPP Client used by the extension.
void Exception(Exception Exception)
Called to inform the viewer of an exception state.
XmppClient Client
XMPP Client.
Represents a case-insensitive string.
Static interface for database persistence. In order to work, a database provider has to be assigned t...
static async Task Update(object Object)
Updates an object in the database.
static async Task Delete(object Object)
Deletes an object in the database.
static Task< IEnumerable< object > > Find(string Collection, params string[] SortOrder)
Finds objects in a given collection.
static async Task Insert(object Object)
Inserts an object into the default collection of the database.
This filter selects objects that conform to all child-filters provided.
This filter selects objects that have a named field equal to a given value.
Base class for all filter classes.
Implements an in-memory cache.
A chunked list is a linked list of chunks of objects of type T .
bool HasFirstItem
If there is a first item in the collection
T RemoveFirst()
Removes the first item in the collection.
void Add(T Item)
Adds an item to the collection.
T[] ToArray()
Returns an array containing all elements of the collection.
Static class that dynamically manages types and interfaces available in the runtime environment.
static bool UnregisterSingleton(object Object, params object[] Arguments)
Unregisters a singleton instance of a type.
static void ReplaceSingleton(object Object, params object[] Arguments)
Replaces a singleton instance of a type.
static object Instantiate(Type Type, params object[] Arguments)
Returns an instance of the type Type . If one needs to be created, it is. If the constructor requires...
Class that keeps track of events and timing for one thread.
ProfilerThread CreateSubThread(string Name, ProfilerThreadType Type)
Creates a new profiler thread.
void Start()
Processing starts.
void Stop()
Processing starts.
void NewState(string State)
Thread changes state.
Static class managing persistent settings.
static Task< int > DeleteWhereKeyLikeAsync(string Key, string Wildcard)
Deletes available settings, matching a search filter.
static Task< Dictionary< string, object > > GetWhereKeyLikeAsync(string Key, string Wildcard)
Gets available settings, matching a search filter.
static async Task< string > GetAsync(string Key, string DefaultValue)
Gets a string-valued setting.
static async Task< bool > SetAsync(string Key, string Value)
Sets a string-valued setting.
Class managing the contents of a temporary file. When the class is disposed, the temporary file is de...
override void Dispose(bool disposing)
Disposes of the object, and deletes the temporary file.
Represents a named semaphore, i.e. an object, identified by a name, that allows single concurrent wri...
Static class of application-wide semaphores that can be used to order access to editable objects.
static async Task< Semaphore > BeginWrite(string Key)
Waits until the semaphore identified by Key is ready for writing. Each call to BeginWrite must be fo...
Static class containing methods that can be used to make sure calls are made from appropriate locatio...
static ICallStackCheck[] Convert(params object[] Sources)
Converts an array of objects into an array of ICallStackCheck objects, assuming each listed source is...
static void CallFromSource(params string[] Sources)
Makes sure the call is made from one of the listed sources.
Contains methods for simple hash calculations.
static byte[] ComputeSHA256Hash(byte[] Data)
Computes the SHA-256 hash of a block of binary data.
static byte[] ComputeHash(HashFunction Function, byte[] Data)
Computes a hash of a block of binary data.
Interface for parameter encryption algorithms.
byte[] Encrypt(string ParameterName, string ParameterType, uint ParameterIndex, string CreatorJid, byte[] ContractNonce, string ClearText)
Encrypts a parameter value.
SymmetricCipherAlgorithms Algorithm
Symmetric Cipher Algorithm used to encrypt parameters.
Abstract base class for End-to-End encryption schemes.
byte[] Sign(byte[] Data)
Signs binary data using the local private key.
byte[] PublicKey
Remote public key.
IE2eEndpoint CreatePrivate(byte[] Secret)
Creates a new endpoint given a private key.
IE2eEndpoint CreatePublic(byte[] PublicKey)
Creates a new endpoint given a public key.
string Namespace
Namespace of the E2E endpoint
bool SharedSecretUseCipherText
If the recipient needs a cipher text to generate the same shared secret.
byte[] GetSharedSecretForDecryption(IE2eEndpoint RemoteEndpoint, byte[] CipherText)
Gets a shared secret for decryption.
byte[] GetSharedSecretForEncryption(IE2eEndpoint RemoteEndpoint, IE2eSymmetricCipher Cipher, out byte[] CipherText)
Gets a shared secret for encryption, and optionally a corresponding cipher text.
string LocalName
Local name of the E2E endpoint
Interface for symmetric ciphers.
Interface for call stack checks.
delegate Task EventHandlerAsync(object Sender, EventArgs e)
Asynchronous version of EventArgs.
IdentityState
Lists recognized legal identity states.
SignWith
Options on what keys to use when signing data.
ContractParts
How the parts of the contract are defined.
ContractStatus
Validation Status of smart contract
ProtectionLevel
Parameter protection levels
ContractVisibility
Visibility types for contracts.
ContractState
Recognized contract states
IdentityStatus
Validation Status of legal identity
ValidationErrorType
Type of validation error.
FilePurpose
Purpose of file uploaded
SymmetricCipherAlgorithms
Enumeration of symmetric cipher algorithms available in the library.
QoSLevel
Quality of Service Level for asynchronous messages. Support for QoS Levels must be supported by the r...
MessageType
Type of message received.
XmppState
State of XMPP connection.
E2ETransmission
End-to-end encryption mode.
ProfilerThreadType
Type of profiler thread.
IdentityState
Lists recognized legal identity states.
HashFunction
Hash method enumeration.
Represents a duration value, as defined by the xsd:duration data type: http://www....
override string ToString()