admin管理员组

文章数量:1334910

I'm trying to encrypt some strings in the frontend with javascript with the some public-private key method in which only the backend could decrypt with the private key, is this possible? how can I achieve it?

I don't mind if it has a really basic encryption as long it has a public and private key

// This is an EXAMPLE of what I want:

//Frontend code:
let message = encrypt("hello word!","public_key");

//Nodejs backend code:
let decrypt_message = decrypt(message, "private_key");

also notice that I'm already using HTTPS but having extra security doesn't hurt anyone :)

thank you in advance ♥

I'm trying to encrypt some strings in the frontend with javascript with the some public-private key method in which only the backend could decrypt with the private key, is this possible? how can I achieve it?

I don't mind if it has a really basic encryption as long it has a public and private key

// This is an EXAMPLE of what I want:

//Frontend code:
let message = encrypt("hello word!","public_key");

//Nodejs backend code:
let decrypt_message = decrypt(message, "private_key");

also notice that I'm already using HTTPS but having extra security doesn't hurt anyone :)

thank you in advance ♥

Share Improve this question edited Aug 6, 2022 at 10:27 mentamarindo asked Jun 18, 2020 at 3:09 mentamarindomentamarindo 6471 gold badge11 silver badges16 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

CryptoJS / crypto-js and JSEncrypt / jsencrypt are the libraries you can use to do so.

You need to encrypt your data encryption key to send to backend and then you can decode this on backend using Private key and encryption key.

I forgot about this question... and 2 years later I found a solution:

Using pre-puted shared keys:

https://medium./sharenowtech/high-speed-public-key-cryptography-in-javascript-part-1-3eefb6f91f77#ea31

You can use the built-in SubtleCrypto API.

Correct me if I'm wrong, but I expect you will only be giving the front-end the public key? Then there is not any use for a "decrypt" function here, as in most RSA implementations, you cannot encrypt with the private key and decrypt with the public key. The "decrypt" function will definitely always error in this implementation.

Also, I'm not 100% sure my code works perfectly, as I didn't try decrypting with the corresponding private key.

testEncryptionAndDecryption();

async function testEncryptionAndDecryption() {
  
  const publicKeyPemString = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy3Xo3U13dc+xojwQYWoJLCbOQ5fOVY8LlnqcJm1W1BFtxIhOAJWohiHuIRMctv7dzx47TLlmARSKvTRjd0dF92jx/xY20Lz+DXp8YL5yUWAFgA3XkO3LSJgEOex10NB8jfkmgSb7QIudTVvbbUDfd5fwIBmCtaCwWx7NyeWWDb7A9cFxj7EjRdrDaK3ux/ToMLHFXVLqSL341TkCf4ZQoz96RFPUGPPLOfvN0x66CM1PQCkdhzjE6U5XGE964ZkkYUPPsy6Dcie4obhW4vDjgUmLzv0z7UD010RLIneUgDE2FqBfY/C+uWigNPBPkkQ+Bv/UigS6dHqTCVeD5wgyBQIDAQAB
-----END PUBLIC KEY-----`;

  let message = await encrypt("hello word!", publicKeyPemString);
  console.log("Encrypted message:", message);

  let decrypt_message = null;

  try {
    decrypt_message = await decrypt(message, publicKeyPemString);
  }
  catch (error) {
    console.log("Message couldn't be decrypted");
  }

  /* the decrypt() method throws an error because the user shouldn't be able to
   * decrypt his own message with the public key
   */
}



function string2ArrayBuffer(string) {
  const len = string.length;
  
  const buffer = new ArrayBuffer(len);
  const uint8Array = new Uint8Array(buffer);
  
  for (let i = 0; i < len; i++) uint8Array[i] = string.charCodeAt(i);
  
  return buffer;
}

function arrayBuffer2String(arrayBuffer) {
  return String.fromCharCode(...new Uint8Array(arrayBuffer));
}

function decodeBase64(base64String) {
  const string = atob(base64String);
  
  return string2ArrayBuffer(string);
}

function encodeBase64(arrayBuffer) {
  const string = arrayBuffer2String(arrayBuffer);
  const base64String = btoa(string);
  return base64String;
}

function pemString2PublicKeyBuffer(pemString) {
  const pemHeader = "-----BEGIN PUBLIC KEY-----";
  const pemFooter = "-----END PUBLIC KEY-----";
  
  if (!(pemString.includes(pemHeader) && pemString.includes(pemFooter))) throw new TypeError(`First argument to pemString2PublicKeyBuffer (received "${pemString}") is not a valid PEM key`);
  
  const pemContents = pemString.slice(pemHeader.length, pemString.length - pemFooter.length);
  
  return decodeBase64(pemContents);
}

async function pemString2PublicKeyCryptoKey(publicKeyPemString) {
  const publicKeyBuffer = pemString2PublicKeyBuffer(publicKeyPemString);  
  return await crypto.subtle.importKey("spki", publicKeyBuffer, { name: "RSA-OAEP", hash: "SHA-256" }, true, ["encrypt"]);
}



async function encrypt(plaintextString, publicKeyPemString) {
  
  const plaintextBuffer = (new TextEncoder).encode(plaintextString).buffer;
  const cryptoKey = await pemString2PublicKeyCryptoKey(publicKeyPemString);
  const ciphertextBuffer = await crypto.subtle.encrypt({ name: "RSA-OAEP" }, cryptoKey, plaintextBuffer);
  
  const ciphertextBase64String = encodeBase64(ciphertextBuffer);
  
  return ciphertextBase64String;
}

// The following function will always error, because you can't decrypt anything with the public key:
async function decrypt(ciphertextBase64String, publicKeyPemString) {
  const ciphertextBuffer = decodeBase64(ciphertextBase64String);
  const cryptoKey = await pemString2PublicKeyCryptoKey(publicKeyPemString);
  const plaintextBuffer = await crypto.subtle.decrypt({ name: "RSA-OAEP" }, cryptoKey, ciphertextBuffer);
  const plaintextString = (new TextDecoder).decode(plaintextBuffer);
}

Note: Many people advise against using cryptography on the front-end, as it may give a false sense of security: https://tonyarcieri./whats-wrong-with-webcrypto

本文标签: javascriptJS frontend encryption with publicprivate keyStack Overflow