m.dorian
m.dorian

Reputation: 499

RSACryptoServiceProvider equivalent in JS

I've been developing an ASP.NET WEB API RESTFUL service to be consumed by an angularjs client. Now, I'm making it secure and I've decided to implemement RSA encryption to get it. So, in the server side I'm using RSACryptoServiceProvider methods with both a public and private key stored in a file. It's nearly enough, but, in the first call of the client, it sends an string of username and password to be authenticated and get a token so I must encrypt that call.

Does anybody know about any tutorial or manual about how to implement something similar in JS to what I'm using in C#?

Here is the piece of code of encryption in the WEB API:

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace MvcPrueba.Models
{
public class Cryptography
{
    #region Types

    #region Enum

    #endregion

    #region Class

    #endregion

    #endregion

    #region Variables

    #endregion

    #region Properties

    #endregion

    #region Constructors/Destructors
    #region Constructors
    protected Cryptography()
    {
    }
    #region Instantiate

    #endregion

    #endregion

    #region Destructors
    public void Dispose()
    {
        throw new NotImplementedException();
    }
    #endregion

    #endregion

    #region Class Logic
    // Generate a new key pair
    public static void GenerateKeys(string publicKeyFileName, string privateKeyFileName)
    {
        // Variables
        CspParameters cspParams = null;
        RSACryptoServiceProvider rsaProvider = null;
        StreamWriter publicKeyFile = null;
        StreamWriter privateKeyFile = null;
        string publicKey = "";
        string privateKey = "";

        try
        {
            // Create a new key pair on target CSP
            cspParams = new CspParameters();
            cspParams.ProviderType = 1; // PROV_RSA_FULL 
            //cspParams.ProviderName; // CSP name
            cspParams.Flags = CspProviderFlags.UseArchivableKey;
            cspParams.KeyNumber = (int)KeyNumber.Exchange;
            rsaProvider = new RSACryptoServiceProvider(cspParams);

            // Export public key
            publicKey = rsaProvider.ToXmlString(false);

            // Write public key to file
            publicKeyFile = File.CreateText(publicKeyFileName);
            publicKeyFile.Write(publicKey);

            // Export private/public key pair 
            privateKey = rsaProvider.ToXmlString(true);

            // Write private/public key pair to file
            privateKeyFile = File.CreateText(privateKeyFileName);
            privateKeyFile.Write(privateKey);
        }
        catch (Exception ex)
        {
            // Any errors? Show them
            Console.WriteLine("Exception generating a new key pair! More info:");
            Console.WriteLine(ex.Message);
        }
        finally
        {
            // Do some clean up if needed
            if (publicKeyFile != null)
            {
                publicKeyFile.Close();
            }
            if (privateKeyFile != null)
            {
                privateKeyFile.Close();
            }
        }

    } // Keys

    // Encrypt a file
    public static void Encrypt(string publicKeyFileName, string plainFileName, string encryptedFileName)
    {
        // Variables
        CspParameters cspParams = null;
        RSACryptoServiceProvider rsaProvider = null;
        StreamReader publicKeyFile = null;
        StreamReader plainFile = null;
        FileStream encryptedFile = null;
        string publicKeyText = "";
        string plainText = "";
        byte[] plainBytes = null;
        byte[] encryptedBytes = null;

        try
        {
            // Select target CSP
            cspParams = new CspParameters();
            cspParams.ProviderType = 1; // PROV_RSA_FULL 
            //cspParams.ProviderName; // CSP name
            rsaProvider = new RSACryptoServiceProvider(cspParams);

            // Read public key from file
            publicKeyFile = File.OpenText(publicKeyFileName);
            publicKeyText = publicKeyFile.ReadToEnd();

            // Import public key
            rsaProvider.FromXmlString(publicKeyText);

            // Read plain text from file
            plainFile = File.OpenText(plainFileName);
            plainText = plainFile.ReadToEnd();

            // Encrypt plain text
            plainBytes = Encoding.Unicode.GetBytes(plainText);
            encryptedBytes = rsaProvider.Encrypt(plainBytes, false);

            // Write encrypted text to file
            encryptedFile = File.Create(encryptedFileName);
            encryptedFile.Write(encryptedBytes, 0, encryptedBytes.Length);
        }
        catch (Exception ex)
        {
            // Any errors? Show them
            Console.WriteLine("Exception encrypting file! More info:");
            Console.WriteLine(ex.Message);
        }
        finally
        {
            // Do some clean up if needed
            if (publicKeyFile != null)
            {
                publicKeyFile.Close();
            }
            if (plainFile != null)
            {
                plainFile.Close();
            }
            if (encryptedFile != null)
            {
                encryptedFile.Close();
            }
        }

    } // Encrypt

    // Decrypt a file
    public static void Decrypt(string privateKeyFileName, string encryptedFileName, string plainFileName)
    {
        // Variables
        CspParameters cspParams = null;
        RSACryptoServiceProvider rsaProvider = null;
        StreamReader privateKeyFile = null;
        FileStream encryptedFile = null;
        StreamWriter plainFile = null;
        string privateKeyText = "";
        string plainText = "";
        byte[] encryptedBytes = null;
        byte[] plainBytes = null;

        try
        {
            // Select target CSP
            cspParams = new CspParameters();
            cspParams.ProviderType = 1; // PROV_RSA_FULL 
            //cspParams.ProviderName; // CSP name
            rsaProvider = new RSACryptoServiceProvider(cspParams);

            // Read private/public key pair from file
            privateKeyFile = File.OpenText(privateKeyFileName);
            privateKeyText = privateKeyFile.ReadToEnd();

            // Import private/public key pair
            rsaProvider.FromXmlString(privateKeyText);

            // Read encrypted text from file
            encryptedFile = File.OpenRead(encryptedFileName);
            encryptedBytes = new byte[encryptedFile.Length];
            encryptedFile.Read(encryptedBytes, 0, (int)encryptedFile.Length);

            // Decrypt text
            plainBytes = rsaProvider.Decrypt(encryptedBytes, false);

            // Write decrypted text to file
            plainFile = File.CreateText(plainFileName);
            plainText = Encoding.Unicode.GetString(plainBytes);
            plainFile.Write(plainText);
        }
        catch (Exception ex)
        {
            // Any errors? Show them
            Console.WriteLine("Exception decrypting file! More info:");
            Console.WriteLine(ex.Message);
        }
        finally
        {
            // Do some clean up if needed
            if (privateKeyFile != null)
            {
                privateKeyFile.Close();
            }
            if (encryptedFile != null)
            {
                encryptedFile.Close();
            }
            if (plainFile != null)
            {
                plainFile.Close();
            }
        }

    } // Decrypt
    #endregion
}
}

Thanks in advance.

Upvotes: 0

Views: 1594

Answers (2)

Chris
Chris

Reputation: 5108

@m.dorian - This is a very bad idea! Please do not try to implement this in any way if you value security and best practices. I would suggest that you read up on the subject thoroughly. In addition, you should ALWAYS hash your user's password and not encrypt them. Passwords should be one-way hashed etc etc.

If you don't know the specifics of data security, I would recommend that you take a step back and either speak to someone that knows what they're doing, or you educate yourself. Especially after all the data compromises reported in the last couple of years. Useful post by Troy Hunt can be found here and this should only be the start!

Upvotes: 1

Alex
Alex

Reputation: 6376

An new API, Web Cryptography API, is currently in draft status but according to MDN it can be used in in the latest versions of almost every major browser.

However, I'm not sure what you're trying to achieve? You said you want client-side encryption of the username and password, but why aren't you just using TLS to encrypt all the traffic? Or are you using the username & password to generate a private key with which to encrypt and decrypt the data client-side so you only have to store the public key on the server?

And a side-note, you are storing the encryption keys in files. How secure are you storing them? When somebody steals the keys all the data is out in the open.

Upvotes: 0

Related Questions