/// <summary> /// Application specific configuration /// This method should initialize any IoC resources utilized by your web service classes. /// </summary> public override void Configure(Container container) { Plugins.Add(new CorsFeature()); this.GlobalRequestFilters.Add((httpReq, httpRes, requestDto) => { // Handles Request and closes Responses after emitting global HTTP Headers if (httpReq.GetHttpMethodOverride() == "OPTIONS") { httpRes.EndRequest(); } }); container.Register(c => DatabaseProvider.PrepareDatabase()); container.Register <IAuthRepository>(c => new OrmLiteAuthRepository(c.Resolve <IDbConnectionFactory>())); container.Resolve <IAuthRepository>().InitSchema(); container.Register <ICacheClient>(new MemoryCacheClient()); Plugins.Add(new AuthFeature( () => new AuthUserSession(), new IAuthProvider[] { new JwtAuthProvider(AppSettings) { AuthKey = AesUtils.CreateKey() }, new BasicAuthProvider(), new CredentialsAuthProvider(), } )); Plugins.Add(new RegistrationFeature()); }
public void Configure(IAppHost appHost) { var AppSettings = appHost.AppSettings; appHost.Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] { //new BasicAuthProvider(), //Sign-in with HTTP Basic Auth new JwtAuthProvider(AppSettings) { AuthKey = AesUtils.CreateKey(), RequireSecureConnection = false, }, new CredentialsAuthProvider(), //HTML Form post of UserName/Password credentials new FacebookAuthProvider(AppSettings), new TwitterAuthProvider(AppSettings), })); appHost.Plugins.Add(new RegistrationFeature()); var userRep = new InMemoryAuthRepository(); appHost.Register <IAuthRepository>(userRep); var authRepo = userRep; var newAdmin = new UserAuth { Email = "*****@*****.**", DisplayName = "Admin User" }; var user = authRepo.CreateUserAuth(newAdmin, "p@55wOrd"); authRepo.AssignRoles(user, new List <string> { "Admin" }); }
/// <summary> /// 解密Comment /// </summary> /// <param name="ori"></param> private void DecryptText(string ori) { var result = AesUtils.Decrypt(ori, UIPanel163Key.AesKey); Debug.Log("" + result); mIpResult.text = result; }
public void Configure(IAppHost appHost) { var AppSettings = appHost.AppSettings; appHost.Plugins.Add(new AuthFeature(() => new CustomUserSession(), new IAuthProvider[] { new CredentialsAuthProvider(AppSettings), //Enable UserName/Password Credentials Auth new JwtAuthProvider(AppSettings) { RequireSecureConnection = false, AuthKey = AesUtils.CreateKey(), //Transient Auth Key }, })); appHost.Plugins.Add(new RegistrationFeature()); //Enable /register Service //override the default registration validation with your own custom implementation appHost.RegisterAs <CustomRegistrationValidator, IValidator <Register> >(); appHost.Register <ICacheClient>(new MemoryCacheClient()); //Store User Sessions in Memory appHost.Register <IAuthRepository>(new InMemoryAuthRepository()); //Store Authenticated Users in Memory CreateUser(appHost, "*****@*****.**", "Admin User", "p@55wOrd", roles: new[] { RoleNames.Admin }); }
public void Can_Send_Encrypted_Message() { var client = CreateClient(); var request = new HelloSecure { Name = "World" }; var aes = new AesManaged { KeySize = AesUtils.KeySize }; var aesKeyBytes = aes.Key.Combine(aes.IV); var rsaEncAesKeyBytes = RsaUtils.Encrypt(aesKeyBytes, SecureConfig.PublicKeyXml); var timestamp = DateTime.UtcNow.ToUnixTime(); var requestBody = timestamp + " POST " + typeof(HelloSecure).Name + " " + request.ToJson(); var encryptedMessage = new EncryptedMessage { EncryptedSymmetricKey = Convert.ToBase64String(rsaEncAesKeyBytes), EncryptedBody = AesUtils.Encrypt(requestBody, aes.Key, aes.IV) }; var encResponse = client.Post(encryptedMessage); var responseJson = AesUtils.Decrypt(encResponse.EncryptedBody, aes.Key, aes.IV); var response = responseJson.FromJson <HelloSecureResponse>(); Assert.That(response.Result, Is.EqualTo("Hello, World!")); }
public (string token, Key privateKey) Login(string email, string password, string pin) { string token = api.Auth.PostAuthResponse(new AuthenticateModel() { Email = email, Password = password }).Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError() .GetResponseObject().Result.Token; api.PinSecurity.GetPinSecurity(pin, token).Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError(); api.Client.GetClientCodes(token).Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError(); string accessToken = api.Client.PostClientCodes(new SubmitCodeModel("0000"), token).Validate.StatusCode(HttpStatusCode.OK) .Validate.NoApiError().GetResponseObject().Result.AccessToken; string encodedPrivateKey = api.Client .PostClientEncodedMainKey(new AccessTokenModel(accessToken), token) .Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError() .GetResponseObject().Result.EncodedPrivateKey; string privateKeyStr = AesUtils.Decrypt(encodedPrivateKey, password); Key privateKey = Key.Parse(privateKeyStr); return(token, privateKey); }
public void Does_Hybrid_RSA_SHA512_AES_MasterKey_and_HmacSha256() { var request = new HelloSecure { Name = "World" }; var msgBytes = request.ToJson().ToUtf8Bytes(); byte[] masterKey, iv; AesUtils.CreateKeyAndIv(out masterKey, out iv); var sha512KeyBytes = masterKey.ToSha512HashBytes(); var cryptKey = new byte[sha512KeyBytes.Length / 2]; var authKey = new byte[sha512KeyBytes.Length / 2]; Buffer.BlockCopy(sha512KeyBytes, 0, cryptKey, 0, cryptKey.Length); Buffer.BlockCopy(sha512KeyBytes, cryptKey.Length, authKey, 0, authKey.Length); var encryptedBytes = AesUtils.Encrypt(msgBytes, cryptKey, iv); var authEncryptedBytes = HmacUtils.Authenticate(encryptedBytes, authKey, iv); var aesKeyNonceBytes = iv.Combine(masterKey); var rsaEncAesKeyNonceBytes = RsaUtils.Encrypt(aesKeyNonceBytes, SecureConfig.PublicKeyXml); var json = ValidateAndDecryptWithMasterKey(rsaEncAesKeyNonceBytes, authEncryptedBytes); var fromJson = json.FromJson <HelloSecure>(); Assert.That(fromJson.Name, Is.EqualTo(request.Name)); }
protected override JwtAuthProvider CreateJwtAuthProvider() { return(new JwtAuthProvider { AuthKey = AesUtils.CreateKey(), RequireSecureConnection = false, }); }
public void Test_Method1() { var kex = AesUtils.CreateKey().ToBase64UrlSafe(); var service = appHost.Container.Resolve<MyServices>(); var response = (HelloResponse)service.Any(new Hello { Name = "World" }); Assert.That(response.Result, Is.EqualTo("Hello, World!")); }
public void Does_throw_on_replayed_messages() { var client = CreateClient(); var request = new HelloSecure { Name = "World" }; byte[] cryptKey, iv; AesUtils.CreateKeyAndIv(out cryptKey, out iv); byte[] authKey = AesUtils.CreateKey(); var cryptAuthKeys = cryptKey.Combine(authKey); var rsaEncCryptAuthKeys = RsaUtils.Encrypt(cryptAuthKeys, SecureConfig.PublicKeyXml); var authRsaEncCryptAuthKeys = HmacUtils.Authenticate(rsaEncCryptAuthKeys, authKey, iv); var timestamp = DateTime.UtcNow.ToUnixTime(); var requestBody = timestamp + " POST " + typeof(HelloSecure).Name + " " + request.ToJson(); var encryptedBytes = AesUtils.Encrypt(requestBody.ToUtf8Bytes(), cryptKey, iv); var authEncryptedBytes = HmacUtils.Authenticate(encryptedBytes, authKey, iv); var encryptedMessage = new EncryptedMessage { EncryptedSymmetricKey = Convert.ToBase64String(authRsaEncCryptAuthKeys), EncryptedBody = Convert.ToBase64String(authEncryptedBytes), }; var encResponse = client.Post(encryptedMessage); try { client.Post(encryptedMessage); Assert.Fail("Should throw"); } catch (WebServiceException ex) { ex.StatusDescription.Print(); var errorResponse = (EncryptedMessageResponse)ex.ResponseDto; authEncryptedBytes = Convert.FromBase64String(errorResponse.EncryptedBody); if (!HmacUtils.Verify(authEncryptedBytes, authKey)) { throw new Exception("EncryptedBody is Invalid"); } var responseBytes = HmacUtils.DecryptAuthenticated(authEncryptedBytes, cryptKey); var responseJson = responseBytes.FromUtf8Bytes(); var response = responseJson.FromJson <ErrorResponse>(); Assert.That(response.ResponseStatus.Message, Is.EqualTo("Nonce already seen")); } }
public override void Configure(Container container) { Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] { new JwtAuthProvider(AppSettings) { AuthKey = AesUtils.CreateKey() }, })); }
public void Does_parse_byte_array_as_Base64() { var authKey = AesUtils.CreateKey(); var appSettings = new DictionarySettings(new Dictionary <string, string> { { "AuthKey", Convert.ToBase64String(authKey) } }); Assert.That(appSettings.Get <byte[]>("AuthKey"), Is.EquivalentTo(authKey)); }
// http://localhost:5000/auth/[email protected]&&password=!Abc1234 // Configure your AppHost with the necessary configuration and dependencies your App needs public override void Configure(Container container) { Plugins.Add(new TemplatePagesFeature()); // enable server-side rendering, see: http://templates.servicestack.net if (Config.DebugMode) { Plugins.Add(new HotReloadFeature()); } Plugins.Add(new RazorFormat()); // enable ServiceStack.Razor SetConfig(new HostConfig { AddRedirectParamsToQueryString = true, DebugMode = AppSettings.Get(nameof(HostConfig.DebugMode), false) }); Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] { //new BasicAuthProvider(), //Sign-in with HTTP Basic Auth new JwtAuthProvider(AppSettings) { AuthKey = AesUtils.CreateKey(), RequireSecureConnection = false, }, new CredentialsAuthProvider(), //HTML Form post of UserName/Password credentials new FacebookAuthProvider(AppSettings), new TwitterAuthProvider(AppSettings), })); Plugins.Add(new RegistrationFeature()); Plugins.Add(new OpenApiFeature { UseBearerSecurity = true, }); container.Register <ICacheClient>(new MemoryCacheClient()); var userRep = new InMemoryAuthRepository(); container.Register <IAuthRepository>(userRep); var authRepo = userRep; var newAdmin = new UserAuth { Email = "*****@*****.**" }; var user = authRepo.CreateUserAuth(newAdmin, "test"); authRepo.AssignRoles(user, new List <string> { "Admin" }); }
/// <summary> /// Decrypt an encrypted text. /// </summary> /// <param name="encryptedText">The encrypted text.</param> /// <param name="options">The decryption options.</param> /// <returns>Returns a decrypted text.</returns> public static string Decrypt(string encryptedText, IDictionary <string, object> options) { var toDecrypt = encryptedText; var decryptedText = string.Empty; if (options == null) { throw new ArgumentNullException(nameof(options)); } var decodeFromBase64 = options.ContainsKey("DecodeFromBase64") && Convert.ToBoolean(options["DecodeFromBase64"], CultureInfo.InvariantCulture); var encodeToBase64 = options.ContainsKey("EncodeToBase64") && Convert.ToBoolean(options["EncodeToBase64"], CultureInfo.InvariantCulture); var method = options.ContainsKey("Method") ? options["Method"].ToString() : string.Empty; switch (method) { // RSA case "RSA": var privateKeyPath = options["PrivateKeyPath"].ToString(); if (privateKeyPath.StartsWith("\"", StringComparison.InvariantCulture)) { privateKeyPath = privateKeyPath.Substring(1, privateKeyPath.Length - 1); } if (privateKeyPath.EndsWith("\"", StringComparison.InvariantCulture)) { privateKeyPath = privateKeyPath.Substring(0, privateKeyPath.Length - 1); } decryptedText = decodeFromBase64 ? RsaUtils.Base64DecodeAndDecrypt(toDecrypt, privateKeyPath) : RsaUtils.Decrypt(toDecrypt, privateKeyPath); break; // AES case "AES": var key = options["key"].ToString(); var initializationValue = options["iniValue"].ToString(); decryptedText = decodeFromBase64 ? AesUtils.Base64DecodeAndDecrypt(toDecrypt, key, initializationValue) : AesUtils.Decrypt(toDecrypt, key, initializationValue); break; // Base64 case "Base64": decryptedText = GeneralUtils.Base64Decode(toDecrypt); break; } return(encodeToBase64 ? GeneralUtils.Base64Encode(decryptedText) : decryptedText); }
public override void Configure(Container container) { Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] { new CredentialsAuthProvider(AppSettings), new JwtAuthProvider(AppSettings) { AuthKey = AesUtils.CreateKey(), RequireSecureConnection = false, }, })); container.Register <IAuthRepository>(c => new InMemoryAuthRepository()); var authRepo = container.Resolve <IAuthRepository>(); try { ((IClearable)authRepo).Clear(); } catch { /*ignore*/ } authRepo.CreateUserAuth(new UserAuth { Id = 1, UserName = "******", FirstName = "First", LastName = "Last", DisplayName = "Display", }, "p@55word"); container.Register(c => createMqServerFn()); var mqServer = container.Resolve <IMessageService>(); mqServer.RegisterHandler <HelloIntro>(ExecuteMessage); mqServer.RegisterHandler <MqAuthOnlyToken>(ExecuteMessage); mqServer.RegisterHandler <MqAuthOnly>(m => { var req = new BasicRequest { Verb = HttpMethods.Post, Headers = { ["X-ss-id"] = m.GetBody().SessionId } }; var response = ExecuteMessage(m, req); return(response); }); mqServer.RegisterHandler <MqRestriction>(ExecuteMessage); mqServer.Start(); }
public void Can_Encrypt_and_Decrypt_with_AES() { var msg = new HelloSecure { Name = "World" }; AesUtils.CreateKeyAndIv(out var cryptKey, out var iv); var encryptedText = AesUtils.Encrypt(msg.ToJson(), cryptKey, iv); var decryptedJson = AesUtils.Decrypt(encryptedText, cryptKey, iv); var decryptedMsg = decryptedJson.FromJson <HelloSecure>(); Assert.That(decryptedMsg.Name, Is.EqualTo(msg.Name)); }
public void Can_Encrypt_and_Decrypt_with_AES_bytes() { var msg = new HelloSecure { Name = "World" }; AesUtils.CreateKeyAndIv(out var cryptKey, out var iv); var encryptedBytes = AesUtils.Encrypt(msg.ToJson().ToUtf8Bytes(), cryptKey, iv); var msgBytes = AesUtils.Decrypt(encryptedBytes, cryptKey, iv); var decryptedMsg = msgBytes.FromUtf8Bytes().FromJson <HelloSecure>(); Assert.That(decryptedMsg.Name, Is.EqualTo(msg.Name)); }
public override void Configure(Container container) { Plugins.Add(new EncryptedMessagesFeature { PrivateKey = SecureConfig.PrivateKeyXml.ToPrivateRSAParameters(), FallbackPrivateKeys = { SecureConfig.FallbackPrivateKeyXml.ToPrivateRSAParameters() }, }); var apiKeyAuth = new ApiKeyAuthProvider(AppSettings); var jwtAuth = new JwtAuthProvider(AppSettings) { AuthKey = AesUtils.CreateKey(), UseTokenCookie = false, // only works with non HTTP Cookies }; Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] { new CredentialsAuthProvider(AppSettings), apiKeyAuth, jwtAuth, })); container.Register <IAuthRepository>(c => new InMemoryAuthRepository()); var authRepo = container.Resolve <IAuthRepository>(); var userAuth = authRepo.CreateUserAuth( new UserAuth { Email = "*****@*****.**" }, "p@55word"); var apiKeys = apiKeyAuth.GenerateNewApiKeys(userAuth.Id.ToString(), "live"); var apiKeyRepo = (IManageApiKeys)authRepo; apiKeyRepo.StoreAll(apiKeys); LiveApiKey = apiKeys[0]; JwtBearerToken = jwtAuth.CreateJwtBearerToken(new AuthUserSession { UserAuthId = userAuth.Id.ToString(), Email = userAuth.Email, IsAuthenticated = true, }); }
public void Can_Send_Encrypted_Message() { var client = CreateClient(); var request = new HelloSecure { Name = "World" }; byte[] cryptKey, authKey, iv; AesUtils.CreateCryptAuthKeysAndIv(out cryptKey, out authKey, out iv); var cryptAuthKeys = cryptKey.Combine(authKey); var rsaEncCryptAuthKeys = RsaUtils.Encrypt(cryptAuthKeys, SecureConfig.PublicKeyXml); var authRsaEncCryptAuthKeys = HmacUtils.Authenticate(rsaEncCryptAuthKeys, authKey, iv); var timestamp = DateTime.UtcNow.ToUnixTime(); var requestBody = timestamp + " POST " + typeof(HelloSecure).Name + " " + request.ToJson(); var encryptedBytes = AesUtils.Encrypt(requestBody.ToUtf8Bytes(), cryptKey, iv); var authEncryptedBytes = HmacUtils.Authenticate(encryptedBytes, authKey, iv); var encryptedMessage = new EncryptedMessage { EncryptedSymmetricKey = Convert.ToBase64String(authRsaEncCryptAuthKeys), EncryptedBody = Convert.ToBase64String(authEncryptedBytes), }; var encResponse = client.Post(encryptedMessage); authEncryptedBytes = Convert.FromBase64String(encResponse.EncryptedBody); if (!HmacUtils.Verify(authEncryptedBytes, authKey)) { throw new Exception("Invalid EncryptedBody"); } var decryptedBytes = HmacUtils.DecryptAuthenticated(authEncryptedBytes, cryptKey); var responseJson = decryptedBytes.FromUtf8Bytes(); var response = responseJson.FromJson <HelloSecureResponse>(); Assert.That(response.Result, Is.EqualTo("Hello, World!")); }
public void Does_Hybrid_RSA_Crypt_and_Auth_AES_with_HMAC_SHA256() { var request = new HelloSecure { Name = "World" }; var timestamp = DateTime.UtcNow.ToUnixTime(); var msg = timestamp + " POST " + request.GetType().Name + " " + request.ToJson(); var msgBytes = msg.ToUtf8Bytes(); byte[] cryptKey, authKey, iv; AesUtils.CreateCryptAuthKeysAndIv(out cryptKey, out authKey, out iv); var encryptedBytes = AesUtils.Encrypt(msgBytes, cryptKey, iv); var decryptedBytes = AesUtils.Decrypt(encryptedBytes, cryptKey, iv); Assert.That(decryptedBytes, Is.EquivalentTo(msgBytes)); var authEncryptedBytes = HmacUtils.Authenticate(encryptedBytes, authKey, iv); var cryptAuthKeys = cryptKey.Combine(authKey); var rsaEncCryptAuthKeys = RsaUtils.Encrypt(cryptAuthKeys, SecureConfig.PublicKeyXml); var authRsaEncCryptAuthKeys = HmacUtils.Authenticate(rsaEncCryptAuthKeys, authKey, iv); var decryptedMsg = ValidateAndDecrypt(authRsaEncCryptAuthKeys, authEncryptedBytes); var parts = decryptedMsg.SplitOnFirst(' '); Assert.That(long.Parse(parts[0]), Is.EqualTo(timestamp)); parts = parts[1].SplitOnFirst(' '); Assert.That(parts[0], Is.EqualTo("POST")); parts = parts[1].SplitOnFirst(' '); Assert.That(parts[0], Is.EqualTo(request.GetType().Name)); var decryptedJson = parts[1]; var decryptedRequest = decryptedJson.FromJson <HelloSecure>(); Assert.That(decryptedRequest.Name, Is.EqualTo(request.Name)); }
public void Does_throw_on_replayed_messages() { var client = CreateClient(); var request = new HelloSecure { Name = "World" }; var aes = new AesManaged { KeySize = AesUtils.KeySize }; var aesKeyBytes = aes.Key.Combine(aes.IV); var rsaEncAesKeyBytes = RsaUtils.Encrypt(aesKeyBytes, SecureConfig.PublicKeyXml); var timestamp = DateTime.UtcNow.ToUnixTime(); var requestBody = timestamp + " POST " + typeof(HelloSecure).Name + " " + request.ToJson(); var encryptedMessage = new EncryptedMessage { EncryptedSymmetricKey = Convert.ToBase64String(rsaEncAesKeyBytes), EncryptedBody = AesUtils.Encrypt(requestBody, aes.Key, aes.IV) }; var encResponse = client.Post(encryptedMessage); try { client.Post(encryptedMessage); Assert.Fail("Should throw"); } catch (WebServiceException ex) { ex.StatusDescription.Print(); var errorResponse = (EncryptedMessageResponse)ex.ResponseDto; var responseJson = AesUtils.Decrypt(errorResponse.EncryptedBody, aes.Key, aes.IV); var response = responseJson.FromJson <ErrorResponse>(); Assert.That(response.ResponseStatus.Message, Is.EqualTo("Nonce already seen")); } }
public void Configure(IAppHost appHost) { var AppSettings = appHost.AppSettings; appHost.Plugins.Add(new AuthFeature(() => new CustomUserSession(), new IAuthProvider[] { new JwtAuthProvider(AppSettings) { AuthKey = AesUtils.CreateKey() }, // Use persistent key to enable JWT's beyond restarts new CredentialsAuthProvider(AppSettings), /* Sign In with Username / Password credentials */ new FacebookAuthProvider(AppSettings), /* Create App https://developers.facebook.com/apps */ new GoogleAuthProvider(AppSettings), /* Create App https://console.developers.google.com/apis/credentials */ new MicrosoftGraphAuthProvider(AppSettings), /* Create App https://apps.dev.microsoft.com */ })); appHost.Plugins.Add(new RegistrationFeature()); //Enable /register Service //override the default registration validation with your own custom implementation appHost.RegisterAs <CustomRegistrationValidator, IValidator <Register> >(); }
public void Configure(IAppHost appHost) { var appSettings = appHost.AppSettings; // Setup Authentication appHost.Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] { new CredentialsAuthProvider(appSettings), // Username/Password credentials new FacebookAuthProvider(appSettings), /* Create App https://developers.facebook.com/apps */ new JwtAuthProvider(appSettings) { AuthKey = AesUtils.CreateKey() }, }) { IncludeOAuthTokensInAuthenticateResponse = true, // Include OAuth Keys in authenticated /auth page }); appHost.Plugins.Add(new RegistrationFeature()); //Enable /register Service // Allow posting messages back to Studio when loaded in an iframe appHost.Plugins.Add(new CorsFeature(allowOriginWhitelist: new[] { "https://localhost:5002" })); }
public string GetApi1SignVerToken() { var signTokenResponse = WalletApi.SignatureVerificationToken.GetKeyConfirmation(wallet.WalletAddress, BearerToken); Assert.That(signTokenResponse.StatusCode, Is.EqualTo(HttpStatusCode.OK)); var signToken = signTokenResponse.ResponseObject.Result.Message.ToString(); var signVerToken = signToken; // WalletApi.PinSecurity.GetPinSecurity(pin, BearerToken).Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError("Please Reset Pin for user in Back Office"); WalletApi.Client.GetClientCodes(BearerToken).Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError(); string accessToken = WalletApi.Client.PostClientCodes(new SubmitCodeModel("0000"), BearerToken).Validate.StatusCode(HttpStatusCode.OK) .Validate.NoApiError().GetResponseObject().Result.AccessToken; string encodedPrivateKey = WalletApi.Client .PostClientEncodedMainKey(new AccessTokenModel(accessToken), BearerToken) .Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError() .GetResponseObject().Result.EncodedPrivateKey; string privateKeyStr = AesUtils.Decrypt(encodedPrivateKey, wallet.WalletKey); Key privateKey = Key.Parse(privateKeyStr); // signToken = privateKey.SignMessage(signToken); var postSignResponse = WalletApi.SignatureVerificationToken.PostKeyConfirmation(new RecoveryTokenChallangeResponse { Email = wallet.WalletAddress, SignedMessage = signToken }, BearerToken); Assert.That(postSignResponse.StatusCode, Is.EqualTo(HttpStatusCode.OK)); return(postSignResponse.ResponseObject.Result.AccessToken); }
public static string CreateEncryptedJweToken(JsonObject jwtPayload, RSAParameters publicKey) { //From: http://self-issued.info/docs/draft-ietf-jose-json-web-encryption-09.html#RSACBCExample var jweHeader = new JsonObject { { "alg", "RSA-OAEP" }, { "enc", "A128CBC-HS256" }, { "kid", Convert.ToBase64String(publicKey.Modulus).Substring(0, 3) }, }; var jweHeaderBase64Url = jweHeader.ToJson().ToUtf8Bytes().ToBase64UrlSafe(); var authKey = new byte[128 / 8]; var cryptKey = new byte[128 / 8]; var cryptAuthKeys256 = AesUtils.CreateKey(); Buffer.BlockCopy(cryptAuthKeys256, 0, authKey, 0, authKey.Length); Buffer.BlockCopy(cryptAuthKeys256, authKey.Length, cryptKey, 0, cryptKey.Length); var aes = Aes.Create(); aes.KeySize = 128; aes.BlockSize = 128; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; using (aes) { aes.GenerateIV(); var iv = aes.IV; aes.Key = cryptKey; var jweEncKey = RsaUtils.Encrypt(cryptAuthKeys256, publicKey, UseRsaKeyLength); var jweEncKeyBase64Url = jweEncKey.ToBase64UrlSafe(); var ivBase64Url = iv.ToBase64UrlSafe(); var aad = jweHeaderBase64Url + "." + jweEncKeyBase64Url; var aadBytes = aad.ToUtf8Bytes(); var payloadBytes = jwtPayload.ToJson().ToUtf8Bytes(); using (var cipherStream = MemoryStreamFactory.GetStream()) using (var encrypter = aes.CreateEncryptor(cryptKey, iv)) using (var cryptoStream = new CryptoStream(cipherStream, encrypter, CryptoStreamMode.Write)) using (var writer = new BinaryWriter(cryptoStream)) { writer.Write(payloadBytes); cryptoStream.FlushFinalBlock(); using (var hmac = new HMACSHA256(authKey)) using (var encryptedStream = MemoryStreamFactory.GetStream()) using (var bw = new BinaryWriter(encryptedStream)) { bw.Write(aadBytes); bw.Write(iv); bw.Write(cipherStream.GetBuffer(), 0, (int)cipherStream.Length); bw.Flush(); var tag = hmac.ComputeHash(encryptedStream.GetBuffer(), 0, (int)encryptedStream.Length); var cipherTextBase64Url = cipherStream.ToBase64UrlSafe(); var tagBase64Url = tag.ToBase64UrlSafe(); var jweToken = jweHeaderBase64Url + "." + jweEncKeyBase64Url + "." + ivBase64Url + "." + cipherTextBase64Url + "." + tagBase64Url; return(jweToken); } } } }
public override void Configure(Container container) { if (Use != null) { Use(container); } if (EnableRazor) { Plugins.Add(new RazorFormat()); } Plugins.Add(new SwaggerFeature()); Plugins.Add(new RequestInfoFeature()); Plugins.Add(new RequestLogsFeature()); Plugins.Add(new ServerEventsFeature()); Plugins.Add(new ValidationFeature()); container.RegisterValidators(typeof(AutoValidationValidator).Assembly); var dbFactory = new OrmLiteConnectionFactory(":memory:", SqliteDialect.Provider); container.Register <IDbConnectionFactory>(dbFactory); dbFactory.RegisterConnection("testdb", "~/App_Data/test.sqlite".MapAbsolutePath(), SqliteDialect.Provider); using (var db = dbFactory.OpenDbConnection()) { db.DropAndCreateTable <Rockstar>(); //Create table if not exists db.Insert(Rockstar.SeedData); //Populate with seed data } using (var db = dbFactory.OpenDbConnection("testdb")) { db.DropAndCreateTable <Rockstar>(); //Create table if not exists db.Insert(new Rockstar(1, "Test", "Database", 27)); } SetConfig(new HostConfig { AdminAuthSecret = "secret", DebugMode = true, }); if (EnableAuth) { Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] { new BasicAuthProvider(AppSettings), new CredentialsAuthProvider(AppSettings), new ApiKeyAuthProvider(AppSettings) { RequireSecureConnection = false }, new JwtAuthProvider(AppSettings) { AuthKey = JwtRsaPrivateKey != null || JwtRsaPublicKey != null ? null : AesUtils.CreateKey(), RequireSecureConnection = false, HashAlgorithm = JwtRsaPrivateKey != null || JwtRsaPublicKey != null ? "RS256" : "HS256", PublicKey = JwtRsaPublicKey, PrivateKey = JwtRsaPrivateKey, EncryptPayload = JwtEncryptPayload, }, }) { IncludeRegistrationService = true, }); container.Resolve <IAuthRepository>().InitSchema(); } }
/// <summary> /// Application specific configuration /// This method should initialize any IoC resources utilized by your web service classes. /// </summary> public override void Configure(Container container) { //Console.WriteLine LogManager.LogFactory = new ConsoleLogFactory(debugEnabled: true); container.Register <IAuthRepository>(c => new OrmLiteAuthRepository(container.Resolve <IDbConnectionFactory>()) { UseDistinctRoleTables = true }); //Create UserAuth RDBMS Tables container.Resolve <IAuthRepository>().InitSchema(); //Also store User Sessions in SQL Server container.RegisterAs <OrmLiteCacheClient, ICacheClient>(); container.Resolve <ICacheClient>().InitSchema(); container.RegisterAs <OrmLiteAuthRepository, IUserAuthRepository>(); //Register Autofac IoC container adapter, so ServiceStack can use it container.Adapter = new AutofacIocAdapter(autoFacContainer); //This method scans the assembly for validators container.RegisterValidators(typeof(Api.General.RegistrationValidator).Assembly); SetConfig(new HostConfig { UseCamelCase = true }); Plugins.Add(new SwaggerFeature { UseBootstrapTheme = true }); Plugins.Add(new PostmanFeature()); Plugins.Add(new CorsFeature()); //Plugins.Add(new RazorFormat()); Plugins.Add(new AutoQueryFeature { MaxLimit = 100 }); Plugins.Add(new AdminFeature()); Plugins.Add(new ValidationFeature()); //Plugins.Add(new RegistrationFeature()); //Add Support for Plugins.Add(new AuthFeature(() => new AuthUserSession(), new IAuthProvider[] { new JwtAuthProvider(AppSettings) { AuthKey = AesUtils.CreateKey(), RequireSecureConnection = false }, new ApiKeyAuthProvider(AppSettings), //Sign-in with API Key new CredentialsAuthProvider(), //Sign-in with UserName/Password credentials new BasicAuthProvider(), //Sign-in with HTTP Basic Auth new DigestAuthProvider(AppSettings), //Sign-in with HTTP Digest Auth new TwitterAuthProvider(AppSettings), //Sign-in with Twitter new FacebookAuthProvider(AppSettings), //Sign-in with Facebook //new YahooOpenIdOAuthProvider(AppSettings), //Sign-in with Yahoo OpenId //new OpenIdOAuthProvider(AppSettings), //Sign-in with Custom OpenId //new GoogleOAuth2Provider(AppSettings), //Sign-in with Google OAuth2 Provider //new LinkedInOAuth2Provider(AppSettings), //Sign-in with LinkedIn OAuth2 Provider //new GithubAuthProvider(AppSettings), //Sign-in with GitHub OAuth Provider //new YandexAuthProvider(AppSettings), //Sign-in with Yandex OAuth Provider //new VkAuthProvider(AppSettings), //Sign-in with VK.com OAuth Provider })); using (var db = container.Resolve <IDbConnectionFactory>().Open()) { //Create the PortalTempUser POCO table if it doesn't already exist db.CreateTableIfNotExists <PortalTempUser>(); } }
/// <summary> /// 修改歌曲信息协程 /// </summary> /// <param name="dirPath"></param> /// <returns></returns> private IEnumerator EditComment(string dirPath) { mCorRunning = true; mIgnoreNum = 0; mAllNum = 0; mFailNum = 0; mDealNum = 0; mMapKeyInfo.Clear(); var pathList = new[] { dirPath }; if (!mIsFile) { //判断单文件还是文件夹 pathList = Directory.GetFiles(dirPath); } var startTime = Time.realtimeSinceStartup; mAllNum = pathList.Length; for (var i = 0; i < pathList.Length; i++) { var path = pathList[i]; if (path.EndsWith("mp3")) { var name = ""; var f = File.Create(path); if (!mTgCover.isOn && f.Tag.Comment.Contains("163")) { //不覆盖 Debug.LogWarning("不覆盖已经有Comment的,跳过:" + f.Tag.Title); mIgnoreNum++; continue; } if (!mTgCoverMatch.isOn && MatchTag.Equals(f.Tag.Description)) { //不覆盖已经准确匹配过的 Debug.LogWarning("不覆盖已经准确匹配过的,跳过:" + f.Tag.Title); mIgnoreNum++; continue; } name = f.Tag.Title.Trim(); if (string.IsNullOrEmpty(name)) { //Tag里面为空就从路径里面获取 name = Path.GetFileNameWithoutExtension(path); // name = path.Substring(path.LastIndexOf("/") + 1); // name = name.Substring(0, name.IndexOf(".")); } Debug.Log("歌曲名字: " + name); if (!string.IsNullOrEmpty(name)) { if (f.Tag.Performers != null && f.Tag.Performers.Length > 0) { //搜索增加名字 name += " " + f.Tag.Performers[0]; } mDealNum++; mTvStatus.text = "正在处理:" + mDealNum + "/" + mAllNum + ",忽略:" + mIgnoreNum + ",失败:" + mFailNum; mLog.Enqueue("正在处理 " + f.Tag.Title); if (mTgDiyUrl.isOn) { //自定义修改 Debug.Log("自定义修改: " + mDiySongID); mMapKeyInfo.Add(path, new SongInfo() { id = mDiySongID, }); } else { yield return(Search(f.Tag, path, name, (songInfo) => { if (songInfo != null) { mMapKeyInfo.Add(path, songInfo); } else { mFailNum++; } f.Dispose(); })); } if (i == pathList.Length - 1 || mMapKeyInfo.Count == DetailNum) { //每20条内容或者最后一条了,就获取详情 Debug.Log("开始获取详情:" + mDealNum); mLog.Enqueue("开始获取详情:" + mDealNum); var idList = new List <int>(); foreach (var keyValuePair in mMapKeyInfo) { idList.Add(keyValuePair.Value.id); } //获取歌曲详情 yield return(GetSongDetail(idList.ToArray(), (songs) => { if (songs != null && songs.Count > 0) { var keyList = mMapKeyInfo.Keys.ToArray(); foreach (var key in keyList) { mMapKeyInfo.TryGetValue(key, out var outInfo); if (outInfo != null) { var isMatch = outInfo.IsMatch; var songInfo = songs.Find(v => v.id == outInfo.id); songInfo.IsMatch = isMatch; //替换搜索的实体为详情得到的实体 mMapKeyInfo[key] = songInfo; } } foreach (var keyValuePair in mMapKeyInfo) { var songInfo = keyValuePair.Value; if (songInfo != null) { var fCache = File.Create(keyValuePair.Key); songInfo.bitrate = fCache.Properties.AudioBitrate * 1000; var comment = JsonMapper.ToJson(songInfo.ToKeyInfo()); fCache.Tag.Comment = "163 key(Don't modify):" + AesUtils.Encrypt("music:" + comment, AesKey); //定义是否完全匹配 fCache.Tag.Description = (songInfo.IsMatch ? MatchTag : ""); fCache.Save(); fCache.Dispose(); var fileName = "/" + Path.GetFileName(keyValuePair.Key); //根据文件名称来删除数据库 mDataDataService?.DeleteRow(fileName); } else { mFailNum++; } } } else { mFailNum += idList.Count; } })); //清空当前歌曲库 mMapKeyInfo.Clear(); } } } } mCorRunning = false; mBtnEdit.GetComponentInChildren <Text>().text = "开始"; yield return(null); Debug.Log("搜索完毕,耗时:" + (Time.realtimeSinceStartup - startTime) + "秒"); mTvStatus.text = "处理完毕:" + mDealNum + "/" + mAllNum + ",忽略:" + mIgnoreNum + ",失败:" + mFailNum; mLog.Enqueue(mTvStatus.text); if (mNeedReOpen) { if (mDealNum > 0) { Debug.Log("需要重启网易云生效"); mLog.Enqueue("请重启网易云生效"); } mDataDataService?.Close(); } }
public void E2EOrdinaryFlowApi1ExtensionsTest() { string initialEtherBalance = ""; string finalEtherBalance = ""; string DESTNATION_ADDRESS = "rLUEUviNDaEU395WAdD7osWbzy6v9FqaMY"; var RippleBalanceAPIURL = $"https://s.altnet.rippletest.net:51234"; var walletBalance = 0d; var finalBalance = 0d; var assetId = "c9cf27b2-9c68-4159-a30f-23a99950d929"; var signToken = ""; var signVerToken = ""; var pin = "1111"; var signedVerificationToken = ""; var WalletId = "da268259-c2f1-414a-96b1-e0fd5b9b724f"; var zeroTransactionId = ""; var extension = ""; var pkSecret = "sapoZtw4oZiwhoHvF6Z7thTGmpaJ6"; var volume = 1m; //Step($"Get latest transaction id for wallet {WalletId}", () => //{ // zeroTransactionId = GetLatestFinishedTransactionId(WalletId); //}); Step("Get initial balance of Ripple waller: bcn initial balance = GET http://ripplerpc:[email protected]:5005/", () => { var json = "{\"method\": \"account_info\",\"params\": [{\"account\": \"rLUEUviNDaEU395WAdD7osWbzy6v9FqaMY\" }]}"; var balancePage = apiV2.CustomRequests.PostResponse(RippleBalanceAPIURL, json); Assert.That(balancePage.StatusCode, Is.EqualTo(HttpStatusCode.OK), "Could not get initial Ripple balance"); initialEtherBalance = JsonConvert.DeserializeObject <ExtensionBalanceResponse>(balancePage.Content).result.account_data.Balance; }); Step("Get initial balance of lykke client wallet. initial balance = GET https://api-test.lykkex.net/api/Wallets assets.id = e58aa37d - dd46 - 4bdb - bac1 - a6d0d44e6dc9 assets.Balance-> % initialBalance % ", () => { var wallet = WalletApi.Wallets.GetWallets(BearerToken); var balances = apiV2.wallets.GetWalletsBalances(BearerToken).ResponseObject; var walletBalances = balances.First().Balances.ToList(); var assetBalance = walletBalances.Find(b => b.AssetId == assetId); walletBalance = assetBalance.Balance; }); Step("GET https://api-test.lykkex.net/api/signatureVerificationToken/KeyConfirmation?email=%email%", () => { var signTokenResponse = WalletApi.SignatureVerificationToken.GetKeyConfirmation(wallet.WalletAddress, BearerToken); Assert.That(signTokenResponse.StatusCode, Is.EqualTo(HttpStatusCode.OK)); signToken = signTokenResponse.ResponseObject.Result.Message.ToString(); signVerToken = signToken; // WalletApi.PinSecurity.GetPinSecurity(pin, BearerToken).Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError("Please Reset Pin for user in Back Office"); WalletApi.Client.GetClientCodes(BearerToken).Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError(); string accessToken = WalletApi.Client.PostClientCodes(new SubmitCodeModel("0000"), BearerToken).Validate.StatusCode(HttpStatusCode.OK) .Validate.NoApiError().GetResponseObject().Result.AccessToken; string encodedPrivateKey = WalletApi.Client .PostClientEncodedMainKey(new AccessTokenModel(accessToken), BearerToken) .Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError() .GetResponseObject().Result.EncodedPrivateKey; string privateKeyStr = AesUtils.Decrypt(encodedPrivateKey, wallet.WalletKey); Key privateKey = Key.Parse(privateKeyStr); // signToken = privateKey.SignMessage(signToken); }); Step("POST https://api-test.lykkex.net/api/signatureVerificationToken/KeyConfirmation", () => { var postSignResponse = WalletApi.SignatureVerificationToken.PostKeyConfirmation(new RecoveryTokenChallangeResponse { Email = wallet.WalletAddress, SignedMessage = signToken }, BearerToken); Assert.That(postSignResponse.StatusCode, Is.EqualTo(HttpStatusCode.OK)); signedVerificationToken = postSignResponse.ResponseObject.Result.AccessToken; }); Step("POST https://api-test.lykkex.net/api/HotWallet/cashout", () => { var postCashOut = WalletApi.HotWallet.PostCashOut(new HotWalletCashoutOperation { AssetId = assetId, DestinationAddress = DESTNATION_ADDRESS, DestinationAddressExtension = "", Volume = (double)volume }, signedVerificationToken, BearerToken); Assert.That(postCashOut.StatusCode, Does.Not.EqualTo(HttpStatusCode.NotFound).And.Not.EqualTo(HttpStatusCode.InternalServerError).And.Not.EqualTo(HttpStatusCode.BadGateway), "Wrong Cashout Status code"); }); Step("Delay ~ 20min cashout confirmation and waiting fo Finished status", () => { if (!WaitForLatestHistoryResponseGotFinishedState(WalletId, TimeSpan.FromMinutes(20))) { Assert.Fail("Cashout comfirmation does not exist afer 20 minutes"); } Assert.That(GetLatestFinishedTransactionId(WalletId), Does.Not.EqualTo(zeroTransactionId), "Latest transaction ID is the same as before test. History service does not know about our transaction. POST cashout failed?"); }); Step("Get Final Balance; final balance = GET https://api-test.lykkex.net/api/Wallets assets.id = e58aa37d - dd46 - 4bdb - bac1 - a6d0d44e6dc9 assets.Balance-> % finalBalance % initialBalance + finalBalance = %Volume - %feeSize", () => { var wallet = WalletApi.Wallets.GetWallets(BearerToken); var balances = apiV2.wallets.GetWalletsBalances(BearerToken).ResponseObject; var walletBalances = balances.First().Balances.ToList(); var assetBalance = walletBalances.Find(b => b.AssetId == assetId); finalBalance = assetBalance.Balance; }); Step("bcn final balance = GET https://ropsten.etherscan.io/address/0x856924997fa22efad8dc75e83acfa916490989a4 . Validate that final balance on ether wallet is initial balance + volume cashout ", () => { var json = "{\"method\": \"account_info\",\"params\": [{\"account\": \"rLUEUviNDaEU395WAdD7osWbzy6v9FqaMY\" }]}"; var balancePage = apiV2.CustomRequests.PostResponse(RippleBalanceAPIURL, json); Assert.That(balancePage.StatusCode, Is.EqualTo(HttpStatusCode.OK), "Could not get initial Ripple balance"); Assert.That(() => decimal.Parse( JsonConvert.DeserializeObject <ExtensionBalanceResponse>(apiV2.CustomRequests.PostResponse(RippleBalanceAPIURL, json).Content).result.account_data.Balance ), Is.EqualTo(decimal.Parse(initialEtherBalance) + volume * (decimal)Math.Pow(10, 6)).After(3).Minutes.PollEvery(2).Seconds); }); }
public void E2EOrdinaryCashOutNumerousTest() { string initialEtherBalance = ""; string finalEtherBalance = ""; string DESTNATION_ADDRESS = "0x856924997fa22efad8dc75e83acfa916490989a4"; var EtherBalanceAPIURL = $"https://api-ropsten.etherscan.io/api?module=account&action=balance&address={DESTNATION_ADDRESS}&tag=latest"; var walletBalance = 0d; var finalBalance = 0d; var assetId = "e58aa37d-dd46-4bdb-bac1-a6d0d44e6dc9"; var signToken = ""; var signVerToken = ""; var pin = "1111"; var signedVerificationToken = ""; var WalletId = "da268259-c2f1-414a-96b1-e0fd5b9b724f"; var zeroTransactionId = ""; Step($"Get latest transaction id for wallet {WalletId}", () => { zeroTransactionId = GetLatestFinishedTransactionId(WalletId); }); Step("Get initial balance of Ether waller: bcn initial balance = GET https://ropsten.etherscan.io/address/0x856924997fa22efad8dc75e83acfa916490989a4 Balance: % somebalance % Ether-> % inicialBcnBalance % ", () => { var balancePage = apiV2.CustomRequests.GetResponse(EtherBalanceAPIURL); Assert.That(balancePage.StatusCode, Is.EqualTo(HttpStatusCode.OK), "Could not get initial ETHER balance"); initialEtherBalance = JsonConvert.DeserializeObject <EtherBalanceObjectModel>(balancePage.Content).result; }); Step("Get initial balance of lykke client wallet. initial balance = GET https://api-test.lykkex.net/api/Wallets assets.id = e58aa37d - dd46 - 4bdb - bac1 - a6d0d44e6dc9 assets.Balance-> % initialBalance % ", () => { var wallet = WalletApi.Wallets.GetWallets(BearerToken); var balances = apiV2.wallets.GetWalletsBalances(BearerToken).ResponseObject; var walletBalances = balances.First().Balances.ToList(); var assetBalance = walletBalances.Find(b => b.AssetId == assetId); walletBalance = assetBalance.Balance; }); Step("GET https://api-test.lykkex.net/api/signatureVerificationToken/KeyConfirmation?email=%email%", () => { var signTokenResponse = WalletApi.SignatureVerificationToken.GetKeyConfirmation(wallet.WalletAddress, BearerToken); Assert.That(signTokenResponse.StatusCode, Is.EqualTo(HttpStatusCode.OK)); signToken = signTokenResponse.ResponseObject.Result.Message.ToString(); signVerToken = signToken; // WalletApi.PinSecurity.GetPinSecurity(pin, BearerToken).Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError("Please Reset Pin for user in Back Office"); WalletApi.Client.GetClientCodes(BearerToken).Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError(); string accessToken = WalletApi.Client.PostClientCodes(new SubmitCodeModel("0000"), BearerToken).Validate.StatusCode(HttpStatusCode.OK) .Validate.NoApiError().GetResponseObject().Result.AccessToken; string encodedPrivateKey = WalletApi.Client .PostClientEncodedMainKey(new AccessTokenModel(accessToken), BearerToken) .Validate.StatusCode(HttpStatusCode.OK).Validate.NoApiError() .GetResponseObject().Result.EncodedPrivateKey; string privateKeyStr = AesUtils.Decrypt(encodedPrivateKey, wallet.WalletKey); Key privateKey = Key.Parse(privateKeyStr); // signToken = privateKey.SignMessage(signToken); }); Step("POST https://api-test.lykkex.net/api/signatureVerificationToken/KeyConfirmation", () => { var postSignResponse = WalletApi.SignatureVerificationToken.PostKeyConfirmation(new RecoveryTokenChallangeResponse { Email = wallet.WalletAddress, SignedMessage = signToken }, BearerToken); Assert.That(postSignResponse.StatusCode, Is.EqualTo(HttpStatusCode.OK)); signedVerificationToken = postSignResponse.ResponseObject.Result.AccessToken; }); Step("POST https://api-test.lykkex.net/api/HotWallet/cashout", () => { var postCashOut = WalletApi.HotWallet.PostCashOut(new HotWalletCashoutOperation { AssetId = assetId, DestinationAddress = DESTNATION_ADDRESS, DestinationAddressExtension = "", Volume = 0.0001 }, signedVerificationToken, BearerToken); Assert.That(postCashOut.StatusCode, Does.Not.EqualTo(HttpStatusCode.NotFound).And.Not.EqualTo(HttpStatusCode.InternalServerError).And.Not.EqualTo(HttpStatusCode.BadGateway), "Wrong Cashout Status code"); for (int i = 0; i < 2; i++) { signedVerificationToken = GetApi1SignVerToken(); postCashOut = WalletApi.HotWallet.PostCashOut(new HotWalletCashoutOperation { AssetId = assetId, DestinationAddress = DESTNATION_ADDRESS, DestinationAddressExtension = "", Volume = 0.0001 }, signedVerificationToken, BearerToken); Assert.That(postCashOut.StatusCode, Does.Not.EqualTo(HttpStatusCode.NotFound).And.Not.EqualTo(HttpStatusCode.InternalServerError).And.Not.EqualTo(HttpStatusCode.BadGateway), "Wrong Cashout Status code"); } }); Step("Delay ~ 20min cashout confirmation and waiting fo Finished status", () => { if (!WaitForLatestHistoryResponseGotFinishedState(WalletId, TimeSpan.FromMinutes(20))) { Assert.Fail("Cashout comfirmation does not exist afer 20 minutes"); } Assert.That(GetLatestFinishedTransactionId(WalletId), Does.Not.EqualTo(zeroTransactionId), "Latest transaction ID is the same as before test. History service does not know about our transaction. POST cashout failed?"); }); Step("Get Final Balance; final balance = GET https://api-test.lykkex.net/api/Wallets assets.id = e58aa37d - dd46 - 4bdb - bac1 - a6d0d44e6dc9 assets.Balance-> % finalBalance % initialBalance + finalBalance = %Volume - %feeSize", () => { var wallet = WalletApi.Wallets.GetWallets(BearerToken); var balances = apiV2.wallets.GetWalletsBalances(BearerToken).ResponseObject; var walletBalances = balances.First().Balances.ToList(); var assetBalance = walletBalances.Find(b => b.AssetId == assetId); finalBalance = assetBalance.Balance; }); Step("bcn final balance = GET https://ropsten.etherscan.io/address/0x856924997fa22efad8dc75e83acfa916490989a4 . Validate that final balance on ether wallet is initial balance + 20* volume cashout ", () => { var balancePage = apiV2.CustomRequests.GetResponse(EtherBalanceAPIURL); Assert.That(balancePage.StatusCode, Is.EqualTo(HttpStatusCode.OK), "Could not get initial ETHER balance"); finalEtherBalance = JsonConvert.DeserializeObject <EtherBalanceObjectModel>(balancePage.Content).result; Assert.That(decimal.Parse(finalEtherBalance), Is.EqualTo(decimal.Parse(initialEtherBalance) + 22 * 100m)); }); }