Showing posts with label security. Show all posts
Showing posts with label security. Show all posts

Mar 13, 2020

Strong Name Signing in .NET

Using a strong name protects your assembly against manipulation.

For example your software using a class named Class1 in ClassLibrary1 namespace.

If you compile a new dll contains ClassLibrary1.Class1 then you can use this dll instead of original one.

This is very basic example but it can be applicable in real life.

To be sure that your software is using your assembly version then you can sign your project.

Microsoft description is:
When a strong-named assembly is created, it contains the simple text name of the assembly, the version number, optional culture information, a digital signature, and the public key that corresponds to the private key used for signing.
Example here shows signing process in Visual Studio. You can use also command line tool (sn.exe).

Coding

Our solution has 2 projects, executable and a class library. Main program is using ClassLibrary1.Class1

using ClassLibrary1;
using System;

namespace strongname
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("strongname loaded");

            Class1 c = new Class1();

            Console.ReadKey();
        }
    }
}


using System;

namespace ClassLibrary1
{
    public class Class1
    {
        public Class1()
        {
            Console.WriteLine("Hello from Class1");
        }
    }
}

Sign

Right click to project in VS and select Properties. In Signing tab check "Sign the assembly" and select "New" in listbox. Enter password for your private key.


This will create a pfx (Personal Information Exchange Format) file in your project folder.

Run

strongname loaded
Hello from Class1

Recompile

If you create a new project with the same namespace, class and functions then you can use the new dll with current executable.

For test change the code and recompile dll in outside of project folder.

csc.exe /t:library /out:ClassLibrary1.dll Class1.cs
Then replace the old ClassLibrary1.dll with the new file.

Result

When you try to run your executable an error will be shown because the new dll has not signed with correct key.

C:\strongname\bin\Debug\strongname.exe

Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=77d705841860f240' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
at strongname.Program.Main(String[] args)

If you completely remove signing from your projects then your manipulated dll will work.

Oct 15, 2018

Encryption function (dotnet & nodejs)

Following functions give same result on dotnet and nodejs platforms.
Nodejs uses "crypto-js" package.
Dotnet uses "System.Security.Cryptography" namespace.

Dotnet


void Main()  
 {  
     string clearText = "oktay";  
     Console.WriteLine("clearText: " + clearText);  
     string encrypted = Crypto.EncryptToBase64(clearText);  
     Console.WriteLine("encrypted: " + encrypted);  
 }  
 public static class Crypto  
 {  
   public static string EncryptToBase64(string decryptedText)  
   {  
     byte[] rawSecretKey = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };  
     string PassPhrase = "passPhrase";  
     MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();  
     byte[] data = Encoding.UTF8.GetBytes(PassPhrase);  
         byte[] passwordKey = x.ComputeHash(data);  
         Console.WriteLine("key: " + BitConverter.ToString(passwordKey).Replace("-", ""));  
         Console.WriteLine("iv : " + BitConverter.ToString(rawSecretKey).Replace("-", ""));  
         RijndaelManaged rijndael = new RijndaelManaged();  
     ICryptoTransform rijndaelEncryptor = rijndael.CreateEncryptor(passwordKey, rawSecretKey);  
     try  
     {  
       byte[] decryptedData = Encoding.UTF8.GetBytes(decryptedText);  
       byte[] newClearData = rijndaelEncryptor.TransformFinalBlock(decryptedData, 0, decryptedData.Length);  
       return Convert.ToBase64String(newClearData, 0, newClearData.Length);  
     }  
     catch (Exception ex)  
     {  
       throw ex;  
     }  
   }  
 }  

Node.js

 
 var CryptoJS = require("crypto-js");  
 function byteArrayToHexString(byteArray) {  
  return Array.prototype.map  
   .call(byteArray, function(byte) {  
    return ("0" + (byte & 0xff).toString(16)).slice(-2);  
   })  
   .join("");  
 }  

 function EncryptToBase64(password) {
  console.log("clearText: " + password); 
  var PassPhrase = "passPhrase";  
  var rawSecretKey = [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 ];
  
  var myRijndaelKeyBytes = CryptoJS.enc.Utf8.parse(PassPhrase);  
  var myRijndaelKey = CryptoJS.MD5(CryptoJS.enc.Utf8.parse(PassPhrase));  
  console.log("key: " + myRijndaelKey);  
  var myRijndaelIV = byteArrayToHexString(rawSecretKey);  
  var ivCodeWords = CryptoJS.enc.Hex.parse(myRijndaelIV);  
  console.log("iv: " + ivCodeWords);  
  var encrypted = CryptoJS.AES.encrypt(  
   CryptoJS.enc.Utf8.parse(password),  
   myRijndaelKey,  
   {  
    iv: ivCodeWords,  
    mode: CryptoJS.mode.CBC,  
    padding: CryptoJS.pad.Pkcs7  
   }  
  );  
  var base64 = CryptoJS.enc.Base64.stringify(encrypted.ciphertext);  
  console.log("encrypted: " + base64);  
 }  
 EncryptToBase64("oktay");  
 return;  

Result

clearText: oktay
key: C6CEC8C6CAA9A579644664F0575DB2F5
iv : 01010101010101010101010101010101
encrypted: S+6CSoMM6no9atihmfyayQ==