Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
IsoDepReplay.cs
1using System;
3using System.Globalization;
4using System.Text;
5using System.Threading.Tasks;
6using System.Xml;
10
11namespace NeuroAccess.Nfc
12{
18 {
19 private readonly XmlDocument replayXml;
20 private readonly IEnumerator replayEnumerator;
21 private readonly DocumentInformation docInfo;
22 private readonly string mrz;
23 private bool eof = false;
24 private bool disposed = false;
25
31 public IsoDepReplay(string ReplayFileName)
32 : this(XML.LoadFromFile(ReplayFileName))
33 {
34 }
35
41 public IsoDepReplay(XmlDocument ReplayXml)
42 {
43 if (ReplayXml?.DocumentElement is null)
44 throw new ArgumentNullException(nameof(ReplayXml), "Missing XML.");
45
46 if (ReplayXml.DocumentElement.Name != "SnifferOutput" ||
47 ReplayXml.DocumentElement.NamespaceURI != "http://waher.se/Schema/SnifferOutput.xsd")
48 {
49 throw new ArgumentException("Not a sniffer output XML file.", nameof(ReplayXml));
50 }
51
52 this.replayXml = ReplayXml;
53 this.replayEnumerator = this.replayXml.DocumentElement.GetEnumerator();
54
55 if (!this.replayEnumerator.MoveNext() ||
56 this.replayEnumerator.Current is not XmlElement E ||
57 E.LocalName != "Info")
58 {
59 throw new ArgumentException("Not an NFC replay sniffer output XML file.", nameof(ReplayXml));
60 }
61
62 this.mrz = GetRows(E).Replace("\r\n", "\n").Replace('\r', '\n').Trim();
63
64 if (!MrzExtensions.ParseMrz(this.mrz, out DocumentInformation? DocInfo))
65 throw new ArgumentException("Invalid Document Information in MRZ in NFC replay sniffer output XML file.", nameof(ReplayXml));
66
67 this.docInfo = DocInfo;
68 }
69
73 public string Mrz => this.mrz;
74
78 public DocumentInformation DocumentInfo => this.docInfo;
79
83 public INfcTag? Tag => null;
84
89 public Task OpenIfClosed()
90 {
91 this.replayEnumerator.Reset();
92 return Task.CompletedTask;
93 }
94
98 public void CloseIfOpen() { }
99
103 public Task<byte[]> GetHighLayerResponse() => Task.FromResult<byte[]>([]);
104
108 public Task<byte[]> GetHistoricalBytes() => Task.FromResult<byte[]>([]);
109
114 public void SetTimeout(int Timeout) { }
115
119 public void Dispose()
120 {
121 this.Dispose(true);
122 GC.SuppressFinalize(this);
123 }
124
128 protected virtual void Dispose(bool Disposing)
129 {
130 if (this.disposed)
131 return;
132
133 if (Disposing)
134 this.CloseIfOpen();
135
136 this.disposed = true;
137 }
138
145 public Task<byte[]> ExecuteCommand(byte[] Command, ICommunicationLayer CommunicationLayer)
146 {
147 CommunicationLayer.TransmitBinary(false, Command);
148
149 if (this.eof)
150 throw Error("End of replay reached.", CommunicationLayer);
151
152 while (this.replayEnumerator.MoveNext())
153 {
154 if (this.replayEnumerator.Current is XmlElement E &&
155 E.LocalName == "Tx" &&
156 AreSame(Command, GetBin(E)))
157 {
158 while (this.replayEnumerator.MoveNext())
159 {
160 if (this.replayEnumerator.Current is XmlElement E2 &&
161 E2.LocalName == "Rx")
162 {
163 return Task.FromResult(GetBin(E2));
164 }
165 }
166 }
167 }
168
169 this.eof = true;
170 throw Error("Command not found in replay.", CommunicationLayer);
171 }
172
173 public string GetInfo(string Prefix, ICommunicationLayer CommunicationLayer)
174 {
175 if (this.eof)
176 throw Error("End of replay reached.", CommunicationLayer);
177
178 while (this.replayEnumerator.MoveNext())
179 {
180 if (this.replayEnumerator.Current is XmlElement E &&
181 E.LocalName == "Info")
182 {
183 string Info = GetRows(E, true);
184
185 if (Info.StartsWith(Prefix, StringComparison.InvariantCultureIgnoreCase))
186 return Info[Prefix.Length..].Trim();
187 }
188 }
189
190 throw Error("Information not found: " + Prefix, CommunicationLayer);
191 }
192
198 public static byte[] GetBin(XmlElement Event)
199 {
200 return Convert.FromBase64String(GetRows(Event, false));
201 }
202
208 public static string GetRows(XmlElement Event)
209 {
210 return GetRows(Event, true);
211 }
212
219 public static string GetRows(XmlElement Event, bool MultiRow)
220 {
221 StringBuilder sb = new();
222
223 foreach (XmlNode N in Event.ChildNodes)
224 {
225 if (N is XmlElement E2 && E2.LocalName == "Row")
226 {
227 sb.Append(E2.InnerText);
228 if (MultiRow)
229 sb.AppendLine();
230 }
231 }
232
233 return sb.ToString();
234 }
235
236 private static bool AreSame(byte[] Bin1, byte[] Bin2)
237 {
238 int i, c = Bin1.Length;
239
240 if (Bin2.Length != c)
241 return false;
242
243 for (i = 0; i < c; i++)
244 {
245 if (Bin1[i] != Bin2[i])
246 return false;
247 }
248
249 return true;
250 }
251
252 private static Exception Error(string Message, ICommunicationLayer CommunicationLayer)
253 {
254 CommunicationLayer.Error(Message);
255 return new Exception(Message);
256 }
257
258 }
259}
Class implementing the IIsoDepInterface interface for serial communication with an NFC chip,...
Definition: IsoDepReplay.cs:18
void SetTimeout(int Timeout)
Sets communication timeout.
void CloseIfOpen()
Closes the interface, if connected.
Definition: IsoDepReplay.cs:98
static string GetRows(XmlElement Event, bool MultiRow)
Gets text data from a sniffer event.
void Dispose()
Disposes the object.
Task OpenIfClosed()
Connects the interface, if not connected.
Definition: IsoDepReplay.cs:89
virtual void Dispose(bool Disposing)
IDisposable.Dispose
static byte[] GetBin(XmlElement Event)
Gets BASE64-encoded binary data from a sniffer event.
Task< byte[]> GetHistoricalBytes()
Return the ISO-DEP historical bytes for NfcA tags.
Task< byte[]> ExecuteCommand(byte[] Command, ICommunicationLayer CommunicationLayer)
Executes an ISO 14443-4 command on the tag.
IsoDepReplay(string ReplayFileName)
Class implementing the IIsoDepInterface interface for serial communication with an NFC chip,...
Definition: IsoDepReplay.cs:31
Task< byte[]> GetHighLayerResponse()
Return the higher layer response bytes for NfcB tags.
static string GetRows(XmlElement Event)
Gets text data from a sniffer event.
IsoDepReplay(XmlDocument ReplayXml)
Class implementing the IIsoDepInterface interface for serial communication with an NFC chip,...
Definition: IsoDepReplay.cs:41
DocumentInformation DocumentInfo
Parsed document information, based on the MRZ field found in replay file.
Definition: IsoDepReplay.cs:78
string Mrz
MRZ field found in replay file.
Definition: IsoDepReplay.cs:73
Contains parsed information from a machine-readable document information string.
Contains MRZ-related Extensions for Machine-Readable Travel Documents.
Definition: MrzExtensions.cs:9
static bool ParseMrz(string MRZ, [NotNullWhen(true)] out DocumentInformation? Info)
Derives Basic Access Control Keys from the second row of the Machine-Readable string in passport (MRZ...
Helps with common XML-related tasks.
Definition: XML.cs:21
Simple base class for classes implementing communication protocols.
void Error(string Error)
Called to inform the viewer of an error state.
void TransmitBinary(int Count)
Called when binary data has been transmitted.
ISO DEP interface, for communication with an NFC Tag.
Interface for an NFC Tag.
Definition: INfcTag.cs:9
Interface for observable classes implementing communication protocols.