简体   繁体   中英

Common encrypt/decrypt code example for C# and Node.js/crypto

I'm attempting to use Application Request Routing (ARR) in IIS for passing a set of paths to a Node.js website. My issue is being able to get/set the authentication ticket on either side.

I just really need a simple example of an Encrypt/Decrypt pair that will work for C# and Node.js close to out of the box with the same results for both. I'll be working on this problem myself as time permits over the next few days, and intend to answer if nobody comes up with an answer before me.

My intention is to write the node side as a connect/express module on the Node.js side. I am already doing a custom authentication in the ASP.Net solution, and can easily replace my current method with something that can be secure from both platforms (so long as they share the same key).


Current code to create the authentication cookie in AccountController.cs

private void ProcessUserLogin(MyEntityModel db, SiteUser user, bool remember=false)
{
  var roles = String.Join("|", value:user.SiteRoles.Select(sr => sr.Name.ToLowerInvariant().Trim()).Distinct().ToArray());

  //update the laston record(s)
  user.UserAgent = Request.UserAgent;
  user.LastOn = DateTimeOffset.UtcNow;
  db.SaveChanges();

  // Create and tuck away the cookie
  var authTicket = new FormsAuthenticationTicket(
    1
    ,user.Username
    ,DateTime.Now
    ,DateTime.Now.AddDays(31) //max 31 days
    ,remember
    ,string.IsNullOrWhiteSpace(roles) ? "guest" : roles
  );
  var ticket = FormsAuthentication.Encrypt(authTicket);
  var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, ticket);
  if (remember) cookie.Expires = DateTime.Now.AddDays(8);
  Response.Cookies.Add(cookie);
}

Current code to read the authentication cookie in Global.asax.cs

void Application_AuthenticateRequest(object sender, EventArgs args)
{
  HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
  if (authCookie == null) return;

  FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);

  string[] roles = authTicket.UserData.Split(new Char[] { '|' });

  //create new generic identity, and corresponding principal...
  var g = new GenericIdentity(authTicket.Name);
  var up = new GenericPrincipal(g, roles);

  //set principal for current request & thread (app will handle transitions from here)
  Thread.CurrentPrincipal = Context.User = up;
}

Relevant portion of the Web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.web>
    <membership>
      <providers>
        <!-- Remove default provider(s), so custom override works -->
        <clear />
      </providers>
    </membership>
  </system.web>
</configuration>

Here is a work example using DES algorithm. reference

using System;
using System.Text;
using System.Security.Cryptography;

public class Test
{
    public static string Encrypt(string toEncrypt, string key, bool useHashing) 
    {     
        byte[] keyArray;     
        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);      

        if (useHashing)     
        {         
            MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
            keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));     
        }     
        else
            keyArray = UTF8Encoding.UTF8.GetBytes(key);      

        var tdes = new TripleDESCryptoServiceProvider();
        tdes.Key = keyArray;     
        // tdes.Mode = CipherMode.CBC;  // which is default     
        // tdes.Padding = PaddingMode.PKCS7;  // which is default

        Console.WriteLine("iv: {0}", Convert.ToBase64String(tdes.IV));

        ICryptoTransform cTransform = tdes.CreateEncryptor();     
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0,
            toEncryptArray.Length);      
        return Convert.ToBase64String(resultArray, 0, resultArray.Length); 
    }  

    public static void Main()
    {
        Console.WriteLine("encrypted as: {0}", Encrypt("12345", "abcdefghijklmnop", false));
    }
}

which outputs

iv: pdMBMjdeFdo=
encrypted as: 3uDkdT6aQ3c=

And use the right algorithm des-ede-cbc in node.js:

var crypto = require('crypto');

var alg = 'des-ede-cbc';

var key = new Buffer('abcdefghijklmnop', 'utf-8');
var iv = new Buffer('pdMBMjdeFdo=', 'base64');

var encrypted = new Buffer('3uDkdT6aQ3c=', 'base64');
var source = '12345';

var cipher = crypto.createCipheriv(alg, key, iv);
var encoded = cipher.update(source, 'ascii', 'base64');
encoded += cipher.final('base64');

console.log(encoded, encrypted.toString('base64'));

var decipher = crypto.createDecipheriv(alg, key, iv);
var decoded = decipher.update(encrypted, 'binary', 'ascii');
decoded += decipher.final('ascii');

console.log(decoded, source);

which outputs

3uDkdT6aQ3c= 3uDkdT6aQ3c=
12345 12345

@xiaoyi answer is correct. In addition, I am just added a bit clear details code.

Encryption with DES algorithm in C#

  public static string EncryptTest(string toEncrypt, string key, bool useHashing)
        {
            byte[] keyArray;
            byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
            byte[] initVectorBytes = Encoding.ASCII.GetBytes("$secure#");

            if (useHashing)
            {
                MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
                keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
            }
            else
                keyArray = UTF8Encoding.UTF8.GetBytes(key);

            var tdes = new TripleDESCryptoServiceProvider();
            tdes.Key = keyArray;
            tdes.Mode = CipherMode.CBC;  // which is default     
            tdes.Padding = PaddingMode.PKCS7;  // which is default
            tdes.IV = initVectorBytes;

            ICryptoTransform cTransform = tdes.CreateEncryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0,
                toEncryptArray.Length);
            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }

When EncryptTest("1234", "abcdefghijklmnop", false) Output: GD/JSd91ZnQ=

Encryption with DES algorithm in nodejs

var algorithm = 'des-ede-cbc';

function encryption(plainText) {

    var key = new Buffer.from("abcdefghijklmnop", 'utf-8');
    var iv = new Buffer.from("$secure#", "ascii");

    var cipher = crypto.createCipheriv(algorithm, key, iv);
    var encoded = cipher.update(plainText, 'ascii', 'base64');
    encoded += cipher.final('base64');

    console.log(encoded);

    return encoded;
}

When encryption("1234") output: GD/JSd91ZnQ=

Node: new Buffer('', '') is deprecated. I replaced it with new Buffer.from()

Decryption with DES algorithm in C#

public static string DecryptTest(string cipherString, string key, bool useHashing)
        {
            byte[] keyArray;
            byte[] toEncryptArray = Convert.FromBase64String(cipherString);
            byte[] initVectorBytes = Encoding.ASCII.GetBytes("$secure#");

            if (useHashing)
            {
                MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
                keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
            }
            else
                 keyArray = UTF8Encoding.UTF8.GetBytes(key);

            var tdes = new TripleDESCryptoServiceProvider();
            tdes.Key = keyArray;
            tdes.Mode = CipherMode.CBC;  // which is default     
            tdes.Padding = PaddingMode.PKCS7;  // which is default
            tdes.IV = initVectorBytes;

            ICryptoTransform cTransform = tdes.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

            return UTF8Encoding.UTF8.GetString(resultArray);
        }

When DecryptTest("GD/JSd91ZnQ=", "abcdefghijklmnop", false) Output: 1234

Decryption with DES algorithm in nodejs

var algorithm = 'des-ede-cbc';

function decryption(chipertext) {

   var key = new Buffer.from("abcdefghijklmnop", 'utf-8');
    var iv = new Buffer.from("$secure#", "ascii");
    var encrypted = new Buffer.from(chipertext, 'base64');

    var decipher = crypto.createDecipheriv(algorithm, key, iv);
    var decoded = decipher.update(encrypted, 'binary', 'ascii');
    decoded += decipher.final('ascii');

    console.log(decoded);

    return decoded;
}

When decryption("GD/JSd91ZnQ=") output: 1234

More details on DES algorithm

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM