/// <summary> /// Creates a SQRLIdentity object from the specified <paramref name="file"/>. /// </summary> /// <param name="file">The full file path of the identity file to be parsed.</param> /// <returns>The imported identity object, or <c>null</c> if the file does not exist.</returns> public static SQRLIdentity FromFile(string file) { if (!File.Exists(file)) { return(null); } byte[] fileBytes = File.ReadAllBytes(file); return(SQRLIdentity.FromByteArray(fileBytes)); }
/// <summary> /// Parses a SQRL identity from the given <paramref name="identityData"/> byte array. /// </summary> /// <param name="identityData">The raw byte representation of a SQRL identity.</param> /// <param name="noHeader">Indicates whether the plaintext sqrl header is missing and checking for it should be skipped or not.</param> public static SQRLIdentity FromByteArray(byte[] identityData, bool noHeader = false) { SQRLIdentity id = new SQRLIdentity(); bool isBase64 = false; int skip = SQRLHEADER.Length; // Check header if (!noHeader) { string sqrlHeader = System.Text.Encoding.UTF8.GetString(identityData.Take(8).ToArray()); if (!sqrlHeader.Equals(SQRLHEADER, StringComparison.OrdinalIgnoreCase)) { Log.Error($"Error parsing identity from byte array: No SQRL header found!"); throw new IOException("Invalid File Exception, not a valid SQRL Identity File"); } if (sqrlHeader.Equals(SQRLHEADER.ToUpper())) { isBase64 = true; } } else { skip = 0; } // Remove header identityData = identityData.Skip(skip).ToArray(); // If we're dealing with a base64url-encoded identity, // decode it to binary first if (isBase64) { identityData = Sodium.Utilities.Base64ToBinary( System.Text.Encoding.UTF8.GetString(identityData), string.Empty, Sodium.Utilities.Base64Variant.UrlSafeNoPadding); } int i = 0; while (i < identityData.Length) { // we need to be able to read type and length if (i + 4 > identityData.Length) { break; } ushort blockLength = BitConverter.ToUInt16(identityData.Skip(i).Take(2).ToArray()); ushort blockType = BitConverter.ToUInt16(identityData.Skip(i + 2).Take(2).ToArray()); // check if specified length exceeds real length if (i + blockLength > identityData.Length) { break; } switch (blockType) { case 0: SQRLBlock0 block0 = new SQRLBlock0(); block0.FromByteArray(identityData.Skip(i).Take(blockLength).ToArray()); id.Blocks.Add(block0); break; case 1: SQRLBlock1 block1 = new SQRLBlock1(); block1.FromByteArray(identityData.Skip(i).Take(blockLength).ToArray()); id.Blocks.Add(block1); break; case 2: SQRLBlock2 block2 = new SQRLBlock2(); block2.FromByteArray(identityData.Skip(i).Take(blockLength).ToArray()); id.Blocks.Add(block2); break; case 3: SQRLBlock3 block3 = new SQRLBlock3(); block3.FromByteArray(identityData.Skip(i).Take(blockLength).ToArray()); id.Blocks.Add(block3); break; default: SQRLBlock block = new SQRLBlock(); block.FromByteArray(identityData.Skip(i).Take(blockLength).ToArray()); id.Blocks.Add(block); break; } i += blockLength; } return(id); }