142 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Linq;
 | |
| using Kreta.Core.Enum;
 | |
| using Kreta.Core.Exceptions;
 | |
| using Kreta.Ellenorzo.Domain.VN.Common;
 | |
| 
 | |
| namespace Kreta.Ellenorzo.BL.VN.Logic
 | |
| {
 | |
|     /// <summary>
 | |
|     /// Author: Madách Ferenc, Kovács Kornél (DevKornél), Érsek Zalán Created On: 2019.11.
 | |
|     /// </summary>
 | |
|     internal class ApiSecurityLogic
 | |
|     {
 | |
|         private readonly ApiSecurity _apiSecurity;
 | |
|         public int ApiSecurityVersion { get; private set; }
 | |
|         public bool IsJogosult { get; private set; } = false;
 | |
| 
 | |
|         private const int BitParityPosition1 = 6;
 | |
|         private const int BitParityPosition2 = 54;
 | |
| 
 | |
|         private const int SumOfRandomNumbersMinimum = 7;
 | |
|         private const int SumOfRandomNumbersMaximum = 38;
 | |
| 
 | |
|         public ApiSecurityLogic(ApiSecurity apiSecurity)
 | |
|         {
 | |
|             _apiSecurity = apiSecurity;
 | |
|             if (_apiSecurity == null) ///Security disabled from config
 | |
|             {
 | |
|                 IsJogosult = true;
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             ApiSecurityVersion = int.Parse(_apiSecurity.SecurityKey.Substring(33, 3));///#7
 | |
|         }
 | |
|         internal void ThrowExceptionIfNotJogosult()
 | |
|         {
 | |
|             if (IsJogosult)
 | |
|             {
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             if (_apiSecurity.SecurityKey != null && ApiSecurityVersion == 1)
 | |
|             {
 | |
|                 IsJogosult = ApiSecurityValidate();
 | |
|             }
 | |
| 
 | |
|             if (!IsJogosult)
 | |
|             {
 | |
|                 throw new BlException(BlExceptionType.NincsJogosultsag);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         private bool ApiSecurityValidate()
 | |
|         {
 | |
|             return _apiSecurity.SecurityKey.Length >= 150 &&
 | |
|                 _apiSecurity.SecurityKey.Length <= 200 &&
 | |
|                 IsBitParityValid() && ///#3
 | |
|                 ContainsSignatureLastChars() && //#6
 | |
|                 ValidateRandomNumbersSum() && ///#4
 | |
|                 ValidateSignature() && ///#5
 | |
|                 IsNoiseAlphaNumeric(); ///#9
 | |
|         }
 | |
| 
 | |
|         private bool IsBitParityValid()
 | |
|         {
 | |
|             bool IsBinary(char c) => c == '0' || c == '1';
 | |
| 
 | |
|             return IsBinary(_apiSecurity.SecurityKey[BitParityPosition1]) &&
 | |
|                 IsBinary(_apiSecurity.SecurityKey[BitParityPosition2]) &&
 | |
|                 _apiSecurity.SecurityKey[BitParityPosition1] != _apiSecurity.SecurityKey[BitParityPosition2];
 | |
|         }
 | |
| 
 | |
|         private bool ValidateRandomNumbersSum()
 | |
|         {
 | |
|             int sumOfRandomNumbers = int.Parse(_apiSecurity.SecurityKey[8].ToString());
 | |
|             sumOfRandomNumbers += int.Parse(_apiSecurity.SecurityKey[30].ToString());
 | |
|             sumOfRandomNumbers += int.Parse(_apiSecurity.SecurityKey[36].ToString());
 | |
|             sumOfRandomNumbers += int.Parse(_apiSecurity.SecurityKey[43].ToString());
 | |
|             sumOfRandomNumbers += int.Parse(_apiSecurity.SecurityKey[49].ToString());
 | |
| 
 | |
|             return sumOfRandomNumbers >= SumOfRandomNumbersMinimum && sumOfRandomNumbers <= SumOfRandomNumbersMaximum;
 | |
|         }
 | |
| 
 | |
|         private bool ValidateSignature()
 | |
|         {
 | |
|             var secretChars = _apiSecurity.SecurityKey.ToCharArray();
 | |
| 
 | |
|             /// #5-1
 | |
|             int step5_1_AsciiValue = _apiSecurity.SecurityKey[28];
 | |
| 
 | |
|             int countRandomChar = _apiSecurity.Signature.ToCharArray().Count(s => s == _apiSecurity.SecurityKey[28]); ///#5-2
 | |
|             int constValue = 7234599;
 | |
| 
 | |
|             int sumValue = countRandomChar + step5_1_AsciiValue + constValue;
 | |
|             string binaryRepresentation = Convert.ToString(sumValue, 2); ///#5-3
 | |
| 
 | |
|             var arraySize = binaryRepresentation.Length;
 | |
| 
 | |
|             for (int i = 0; i < 31; i++)
 | |
|             {
 | |
|                 secretChars[90 - i] = i < arraySize ? binaryRepresentation[arraySize - i - 1] : '0';
 | |
|             }
 | |
| 
 | |
|             ///#5-4
 | |
|             int offset = int.Parse(secretChars[8].ToString());
 | |
|             var startBitPosition = 59;
 | |
| 
 | |
|             void SwapPositions(int xIndex, int yIndex)
 | |
|             {
 | |
|                 (secretChars[xIndex], secretChars[yIndex]) = (secretChars[yIndex], secretChars[xIndex]);
 | |
|             }
 | |
| 
 | |
|             SwapPositions(startBitPosition + offset, startBitPosition + 31);
 | |
|             SwapPositions(startBitPosition + 10 + int.Parse(secretChars[30].ToString()), startBitPosition + offset);
 | |
|             SwapPositions(startBitPosition + int.Parse(secretChars[43].ToString()), startBitPosition + 17 + int.Parse(secretChars[49].ToString()));
 | |
|             SwapPositions(startBitPosition + int.Parse(secretChars[49].ToString()), startBitPosition + 30 - int.Parse(secretChars[49].ToString()));
 | |
| 
 | |
|             var generatedSecretKey = new string(secretChars).Substring(startBitPosition, 32);
 | |
|             return _apiSecurity.SecurityKey.Substring(startBitPosition, 32) == generatedSecretKey;
 | |
|         }
 | |
| 
 | |
|         public bool ContainsSignatureLastChars()
 | |
|         {
 | |
|             return _apiSecurity.SecurityKey.Substring(99, 3) == _apiSecurity.Signature.Substring(_apiSecurity.Signature.Length - 3, 3);
 | |
|         }
 | |
| 
 | |
|         public bool IsNoiseAlphaNumeric() ///#9
 | |
|         {
 | |
|             int[] expectedNoisePositions = new int[6] { 42, 45, 94, 105, 114, 126 };
 | |
| 
 | |
|             foreach (int i in expectedNoisePositions)
 | |
|             {
 | |
|                 if (!char.IsLetterOrDigit(_apiSecurity.SecurityKey[i]))
 | |
|                 {
 | |
|                     return false;
 | |
|                 }
 | |
|             }
 | |
|             return true;
 | |
|         }
 | |
|     }
 | |
| }
 |