diff --git a/CryptoExchange.Net/Authentication/ApiCredentials.cs b/CryptoExchange.Net/Authentication/ApiCredentials.cs index 2c6d65d..53c00f4 100644 --- a/CryptoExchange.Net/Authentication/ApiCredentials.cs +++ b/CryptoExchange.Net/Authentication/ApiCredentials.cs @@ -1,5 +1,8 @@ using System; +using System.IO; using System.Security; +using System.Text; +using Newtonsoft.Json.Linq; namespace CryptoExchange.Net.Authentication { @@ -8,12 +11,12 @@ namespace CryptoExchange.Net.Authentication /// /// The api key to authenticate requests /// - public SecureString Key { get; } + public SecureString Key { get; private set; } /// /// The api secret to authenticate requests /// - public SecureString Secret { get; } + public SecureString Secret { get; private set; } /// /// The private key to authenticate requests @@ -50,17 +53,49 @@ namespace CryptoExchange.Net.Authentication if (string.IsNullOrEmpty(key) || string.IsNullOrEmpty(secret)) throw new ArgumentException("Key and secret can't be null/empty"); - var secureApiKey = new SecureString(); - foreach (var c in key) - secureApiKey.AppendChar(c); - secureApiKey.MakeReadOnly(); - Key = secureApiKey; + Key = CreateSecureString(key); + Secret = CreateSecureString(secret); + } - var secureApiSecret = new SecureString(); - foreach (var c in secret) - secureApiSecret.AppendChar(c); - secureApiSecret.MakeReadOnly(); - Secret = secureApiSecret; + /// + /// Create Api credentials providing a stream containing json data. The json data should include two values: apiKey and apiSecret + /// + /// The stream containing the json data + /// A key to identify the credentials for the API. For example, when set to `binanceKey` the json data should contain a value for the property `binanceKey`. Defaults to 'apiKey'. + /// A key to identify the credentials for the API. For example, when set to `binanceSecret` the json data should contain a value for the property `binanceSecret`. Defaults to 'apiSecret'. + public ApiCredentials(Stream inputStream, string identifierKey = null, string identifierSecret = null) + { + using (var reader = new StreamReader(inputStream, Encoding.ASCII, false, 512, true)) + { + var stringData = reader.ReadToEnd(); + var jsonData = JToken.Parse(stringData); + var key = TryGetValue(jsonData, identifierKey ?? "apiKey"); + var secret = TryGetValue(jsonData, identifierSecret ?? "apiSecret"); + + if (key == null || secret == null) + throw new ArgumentException("apiKey or apiSecret value not found in Json credential file"); + + Key = CreateSecureString(key); + Secret = CreateSecureString(secret); + } + + inputStream.Seek(0, SeekOrigin.Begin); + } + + protected string TryGetValue(JToken data, string key) + { + if (data[key] == null) + return null; + return (string) data[key]; + } + + protected SecureString CreateSecureString(string source) + { + var secureString = new SecureString(); + foreach (var c in source) + secureString.AppendChar(c); + secureString.MakeReadOnly(); + return secureString; } public void Dispose()