Skip to content

Instantly share code, notes, and snippets.

@revskill10
Forked from QingpingMeng/EncryptSmallData.md
Created December 11, 2023 07:38
Show Gist options
  • Save revskill10/5bc96a556553443cc8ebf55585c473c9 to your computer and use it in GitHub Desktop.
Save revskill10/5bc96a556553443cc8ebf55585c473c9 to your computer and use it in GitHub Desktop.
Encrypt data using JavaScript in browser with RSA public key generated in C# without library

This is an example to demo how you generate the RSA key pair from server side(.NetCore 3.1) and pass the public key to the client(Browser) for encrypting the data that <= 245 bytes.

RSA-2048 can only support to encrypt up to 245 bytes data.

Generate RSA key pair in C# (.Net Core 3.1):

using var rsaProvider = new RSACng();
// spki is used for browser side encryption
var spki = Convert.ToBase64String(rsaProvider.ExportSubjectPublicKeyInfo());
var encodedPrivateKey = Convert.ToBase64String(rsaProvider.ExportPkcs8PrivateKey());

Encrypt data using browser SubtleCrypto API:

function base64ToArrayBuffer(base64) {
    var binary_string = window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array(len);
    for (var i = 0; i < len; i++) {
        bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
}

function arrayBufferToBase64( buffer ) {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
}

async function importPublicKey(spki){
  const binaryDer = base64ToArrayBuffer(spki);
  var cryptoKey = await window.crypto.subtle
    .importKey(
    "spki",
        binaryDer,
        {
          name: 'RSA-OAEP',
          modulusLength: 256,
          hash:  { name: 'sha-256' }
        },
        false,
        ["encrypt"]
    );
  return cryptoKey;
}

async function encyptData(message, cryptoKey){
 let enc = new TextEncoder();
 let encodedMessage = enc.encode(message);
 var encryptedData = await window.crypto.subtle.encrypt(
    {
      name: "RSA-OAEP"
    },
    publicKey,
    encodedMessage
  );
  var encodedData = arrayBufferToBase64(encryptedData);
  return encodedData;
}

// this is spki from C# code.
var spki = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyu9pSV8qF/VUG0MP2ekdlftLS5Ad/wwrF0WCKIfIrSYO6T4vblyuGweQbXKscEuvS2Z8wP4TFU3JSPhRaq7RnFWs0c/UBaQrKSeYEH9iXjJlyGT4N9Shz4lAMLHiMTfxG5fDe\u002B/jUbbEEMXAdcE13lVqUtNLNnEVNq3M1nD5a5MlqCDkdphAaVPlCYcwPZ4v2BEa4ITdejMdJKRiT5jdhFYKUYp0ELtTKm1vU6vSAn6sJvkWJGW5vufOT\u002BJPgxI7o\u002BZfIXP6ln7TSB71KjeY4FrFctPCI/L43wla0LAyjlfgSTQNf9E0XxZnaVCcQe741jhDYS27jHvfAoo/SNLk6QIDAQAB";
var key = await importPublicKey(spki);
var encryptedData = await encryptData("hello world", key);

Decrypt the data in C# that encrypted in browser:

    using var importedRsa = new RSACng();
    var span = (ReadOnlySpan<byte>)Convert.FromBase64String("<EncodedExportedPkcs8PrivateKey>");
    importedRsa.ImportPkcs8PrivateKey(span, out int _);
    var data = Console.ReadLine();
    var bytes = Convert.FromBase64String(data);
    var decryptedBytes = importedRsa.Decrypt(bytes, RSAEncryptionPadding.OaepSHA256);
    var decryptedData = Encoding.UTF8.GetString(decryptedBytes));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment