Thursday, March 7, 2024

Encrypt/Decrypt the App.Config

Program.cs
using System;
using System.Diagnostics;
using System.IO;
namespace EncryptAppConfig
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            const string aspNetRegIisPath = @"c:\Windows\Microsoft.NET\Framework\v4.0.30319\";
            var configFile = "C:\\Users\\SamalSub\\Desktop\\EncryptAppConfig\\BSS.SubApp.App1.exe.config";
            var path = Path.GetDirectoryName(configFile);
            var webConfigFile = Path.Combine(path, "Web.config");
            //Rename to web.config
            if (File.Exists(configFile)) File.Move(configFile, webConfigFile);
            //Encrypt appSettings
            var tagCmd = $"aspnet_regiis -pef appSettings {path}";
            //tagCmd = $"aspnet_regiis -pdf appSettings {path}";
            var encryptTagCmdLine = $"{aspNetRegIisPath}{tagCmd}";
            ExecuteEncryptCmd(encryptTagCmdLine);
            //Rename to ***.exe.config
            if (File.Exists(webConfigFile)) File.Move(webConfigFile, configFile);
            Console.ReadKey();
        }
        private static void ExecuteEncryptCmd(string encryptTagCmdLine)
        {
            var startInfo = new ProcessStartInfo("cmd", "/c " + encryptTagCmdLine)
            {
                WindowStyle = ProcessWindowStyle.Hidden,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                CreateNoWindow = true
            };
            var process = Process.Start(startInfo);
            while (!process.StandardOutput.EndOfStream)
            {
                Console.WriteLine(process.StandardOutput.ReadLine());
            }
            process.Close();
        }
    }
}


EncryptAppConfig.ps1
[CmdletBinding()]
Param(   
    [parameter(Mandatory=$false, HelpMessage="Encrypt the secure app settings")]
    [switch]$Encrypt,
    [parameter(Mandatory=$false, HelpMessage="Decrypt the secure app settings")]
    [switch]$Decrypt
)
$ErrorActionPreference = "Stop"
function Get-EncryptionMode()
{
    if($Encrypt.IsPresent -and $Decrypt.IsPresent) { Write-Error "Use either -Encrypt or -Decrypt" }
    if($Decrypt.IsPresent)
    { 
        return "Decrypt"
    }
    
    return "Encrypt"
}
function Find-ConfigurationFile()
{
    $configFiles  = @(Get-ChildItem -Filter "*.exe.config")
    $configFiles += @(Get-ChildItem -Filter "App.config")
    if($configFiles.Count -gt 1) { Write-Error ("Found more than one configuration file: {0}" -f [string]::Join(", ", $configFiles.Name)) }
    if($configFiles.Count -ne 1) { Write-Error "Could not find the .config file" }
    return $configFiles.Get(0)
}
function Get-DotNetFrameworkDirectory()
{
    $([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory())
}
function Copy-ToTempWebConfig($configurationFile)
{
    if (!(Test-Path -path ".\temp")) 
    {
        Write-Verbose ("Creating temp directory {0}" -f ".\temp")
        New-Item ".\temp" -Type Directory
    }
    Copy-Item $configurationFile "temp\Web.config"
    return Get-Item "temp\Web.config"
}
function Copy-FromTempWebConfig($configurationFile)
{
    Move-Item "temp\Web.config" $configurationFile -Force | Out-Null
    if((Get-ChildItem ".\temp").Count -eq 0)
    {
        Write-Verbose ("Removing empty temp directory {0}" -f ".\temp")
        Remove-Item ".\temp"
    }
}
function Encrypt-ConfigurationSection([string] $configurationPath, $mode){  
  $currentDirectory = (Get-Location)
  Set-Location (Get-DotNetFrameworkDirectory)
  if($mode -eq "Decrypt")
  {
    .\aspnet_regiis -pdf "secureAppSettings" "$configurationPath"
  } else
  {
    .\aspnet_regiis -pef "secureAppSettings" "$configurationPath"
  }
  Set-Location $currentDirectory
}
$mode = Get-EncryptionMode
$configurationFile = (Find-ConfigurationFile)
Write-Verbose ("{0} configuation file {1}" -f $mode, $configurationFile.FullName)
$tempFile = Copy-ToTempWebConfig $configurationFile
Write-Verbose ("Attempting to {0} {1}" -f $mode, $configurationFile.FullName)
Encrypt-ConfigurationSection $tempFile.Directory.FullName $mode
Copy-FromTempWebConfig $configurationFile
InPowershell
./EncryptAppConfig.ps1

Monday, January 15, 2024

What's new in C# 12

 C# 12 includes the following new features. You can try these features using the latest Visual Studio 2022 version or the .NET 8 SDK.

Tuesday, September 27, 2022

Sql server Merge alternative(left join/if not exists) ---better performance than merge

 -- MERGE 

MERGE #Target t

    USING #Source s

    ON s.ID = t.ID

    WHEN MATCHED

        THEN     UPDATE

            SET Value = s.Value

    WHEN NOT MATCHED

        THEN     INSERT

                ( ID, Value )

            VALUES

                ( s.ID

                , s.Value

                );


-- UPDATE/INSERT

BEGIN TRANSACTION T1; 

UPDATE t

    SET Value = s.Value

    FROM #Target t

    INNER JOIN #Source s

    ON s.ID = t.ID;


INSERT INTO #Target

        SELECT s.ID

              , s.Value

        FROM #Source s

        LEFT JOIN #Target t

        ON s.ID = t.ID

        WHERE t.ID IS NULL;

#################################

insert into [SubProjSchema].[Products]([ProductName],[ProductId],[UnitPrice],[CreatedBy])

SELECT [SPTI].[ProductName]

  ,[SPTI].[ProductId]

  ,[SPTI].[UnitPrice]

  ,[User]

FROM @p1 [SPTI]

left join [SubProjSchema].[Products] [PRD] on [SPTI].[ProductId] = [PRD].[ProductId]

where [PRD].ProductId is null


insert into [SubProjSchema].[Products]([ProductName],[ProductId],[UnitPrice],[CreatedBy])

SELECT [SPTI].[ProductName]

  ,[SPTI].[ProductId]

  ,[SPTI].[UnitPrice]

  ,[User]

FROM @p1 [SPTI]

WHERE NOT EXISTS(SELECT 1 FROM [SubProjSchema].[Products] [PRD] WHERE [SPTI].[ProductId] = [PRD].[ProductId])

#################################

COMMIT TRANSACTION T1;

Tuesday, February 15, 2022

SSIS -Set database password without clear text - SENSITIVE PARAMETERS - GetSensitiveValue()

SSIS -Set database password without clear text -  SENSITIVE PARAMETERS - GetSensitiveValue()









public void Main()
       {
           try
           {
               string strPassword = Dts.Variables["$Project::up_DBPassword"].GetSensitiveValue().ToString();
               if (!string.IsNullOrEmpty(strPassword))
               {
                   Dts.Variables["User::uv_DBPasswordSensitiveValue"].Value = strPassword;
               }
               Dts.TaskResult = (int)ScriptResults.Success;
           }
           catch (Exception e)
           {
               Dts.Log(e.Message, 0null);
               Dts.TaskResult = (int)ScriptResults.Failure;
               throw (e);
           }
           Dts.TaskResult = (int)ScriptResults.Success;
       }



Monday, March 9, 2020

Cryptography in .NET - C#

Symmetric Key Encryption

One usual way to storing password is using encryption. it's a two-way process. That means the password is encrypted using the secret key when storing and decrypt using the same key for the password authentication.

It's better than storing the password as plain text. But key management is the challenge. Where do you save that key? If it is a database, It won't be difficult for the hacker who got the encrypted password by hacking the database and decrypt it using the same key.

.NET provides multiple symmetric algorithms and multiple implementations for some algorithms:

AES: AESManaged, AesCng, AesCryptoServiceProvider
DES: DESCryptoServiceProvider
RC2: RC2CryptoServiceProvider
Rijndael: RijndaelManaged
TripleDES: TripleDESCng, TripleDESCryptoServiceProvider

 Asymmetric Key Encryption

So instead of using symmetric key encryption algorithm. we can use asymmetric key encryption algorithm like RSA where client uses public key to encrypt the password and sends it to the server for storage. When authenticate a private key is used to decrypt the password. That private key should be kept secret. This is also not a great solution as the key management is difficult like the previous way.

.NET provides multiple asymmetric algorithms and multiple implementations for some algorithms:

DSA: DSACng, DSACryptoServiceProvider, DSAOpenSsl
ECDiffieHellman: ECDiffieHellmanCng, ECDiffieHellmanOpenSsl
ECDsa: ECDsaCng, ECDsaOpenSsl
RSA: RSACng, RSACryptoServiceProvider, RSAOpenSsl

Hashing

If we use Hashing there won't be any over head of key management. Also no need to decrypt the password back to plain text. Hashing is one way operation. Once a data is hashed we cannot reverse and get the original message, It has four important properties,
  • Easy to compute the hash value for any given message
  • Not possible to generate a message from the given hash
  • Not possible to modify a message without changing the hash
  • Not possible to find two different messages with the same hash

Salted Hash

It is common for a web application to store in a database the hash value of a user's password. Without a salt, a successful SQL injection attack may yield easily crackable passwords. Because many users re-use passwords for multiple sites, the use of a salt is an important component of overall web application security

If we append a random value with a hashed password, Which is difficult for the attacker to hack using brute force or rainbow table attack. The random value is called Salt. The Salted hash and the Salt will be stored in the database as the Salt is required when the password authentication.


Monday, November 18, 2019

Usefull extension methods


// foreach with a "manual" index
int index = 0;
foreach (var item in collection)
{
    DoSomething(item, index);
    index++;
}
// normal for loop
for (int index = 0; index < collection.Count; index++)
{
    var item = collection[index];
    DoSomething(item, index);
}
It’s something that has always annoyed me; couldn’t we have the benefits of both foreach and for?
It turns out that there’s a simple solution, using Linq and tuples. Just write an extension method like this:
using System.Linq;
...
public static IEnumerable<(T item, int index)> WithIndex<T>(this IEnumerable<T> source)
{
    return source.Select((item, index) => (item, index));
}
Do this:
foreach (var (item, index) in collection.WithIndex())
{
    DoSomething(item, index);
}

----------------------------------------------------------------------------------------------------------------


Multilist collection by Tuple
           IList<Tuple<string, string, string, string, string>> listOfData = new List<Tuple<string, string, string, string, string>>();
            foreach (var item in interactionDataSetInformation)
            {
                listOfData.Add(new Tuple<string, string, string, string, string>(item.ICNOcurs, item.MessageType, item.Revision, item.EntityState, item.EntityStatus));
            }
Multilist collection by ArrayList

            ArrayList listOfData = new ArrayList();
            foreach (var item in interactionDataSetInformation)
            {
                listOfData.Add(new string[] { item.ICNOcurs, item.MessageType, item.Revision, item.EntityState, item.EntityStatus });
            }
            ArrayList listOfData = interactionDataSetInformation.ToArrayList<InteractionDataSetInformation>();

Extension methods
  public static DataTable ToDataTable<T>(this IEnumerable<T> data)
        {
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
            DataTable table = new DataTable();
            foreach (PropertyDescriptor prop in properties)
            {
                table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
            }
            foreach (T item in data)
            {
                DataRow row = table.NewRow();
                foreach (PropertyDescriptor prop in properties)
                    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                table.Rows.Add(row);
            }
            return table;
        }

        public static List<T> ToList<T>(this ArrayList arrayList)
        {
            List<T> list = new List<T>(arrayList.Count);
            foreach (T instance in arrayList)
            {
                list.Add(instance);
            }
            return list;
        }

        public static ArrayList ToArrayList<T>(this IEnumerable<T> list)
        {
            ArrayList arrayList = new ArrayList();
            foreach (T item in list)
            {
                List<string> listString = new List<string>();
                foreach (PropertyInfo prop in typeof(T).GetProperties())
                {
                    listString.Add((prop.GetValue(item) == null) ? string.Empty : prop.GetValue(item).ToString());
                }
                string[] _item = listString.ToArray();
                arrayList.Add(_item);
            }
            return arrayList;
        }
    }
-------------------------------------------------------------------------------------------------------------------------

Encrypt/Decrypt the App.Config

Program.cs using System; using System.Diagnostics; using System.IO; namespace EncryptAppConfig {     internal class Program     {         pr...