Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.3k views
in Technique[技术] by (71.8m points)

encryption - Encrypt/Decrypt String using Public/Private Key in Java and Javascript

I am generating a public and private key pair in javascript. The public key is being sent to the server where I have java code that encrypts the string. When I try to decrypt the string in Javascript using a private key I get an error. Here is the Javascript code I used.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class CryptographyService {
  private publicKey: string;
  private privateKey: string;
  public randomKey: string;
  private keyPair: CryptoKeyPair;
  public exportedKey: string;

  constructor() {
    /**Generate the public and private key */
    this.generateKeys()
      .then(() => {
        return this.exportKey(this.keyPair.publicKey);
      })
      .then(() => {});
  }

  public setPublicKey(key: string) {
    this.publicKey = key;
  }
  public setRandomKey(key: string) {
    this.randomKey = key;
  }

  public setPrivateKey(key: string) {
    this.privateKey = key;
  }

  public async encryptMessage(text: String) {
    const { default: NodeRSA } = await import('node-rsa');
    const key = NodeRSA(this.publicKey, 'pkcs8-public');
    return key.encrypt(text, 'base64');
  }

  // For subscription key encryption and decryption
  private async generateKeys() {
    const keyPair = await crypto.subtle.generateKey(
      {
        name: 'RSA-OAEP',    //algorithm
        modulusLength: 2048,
        publicExponent: new Uint8Array([1, 0, 1]),
        hash: 'SHA-256'
      },
      true,
      ['encrypt', 'decrypt']
    );
    this.keyPair = keyPair; /**{
                                  publicKey: 
                                  privateKey: 
                                } */
  }

  private async exportKey(key: CryptoKey) {
    /** exportKey() it takes as input a CryptoKey object and gives you the key in an external, portable format.
     * crypto.subtle.exportKey(format, key); : returns a promise
     * spki format is used to import/export RSA or Elliptic Curve public keys.
     */
    const exported = await crypto.subtle.exportKey('spki', key); //Returns an ArrayBuffer
    const exportedAsString = this.ab2str(exported); // Converts ArrayBuffer to String
    /**btoa encodes a string to base64 */
    const exportedAsBase64 = window.btoa(exportedAsString);
    this.exportedKey = exportedAsBase64;
  }

  // Uses private key to decrypt message sent from the backend
  public async decryptMessage(input: string) {
    const ciphertext = this.str2ab(input);
    const decrypted = await window.crypto.subtle.decrypt(
      {
        name: 'RSA-OAEP'
      },
      this.keyPair.privateKey,
      ciphertext
    );

    const dec = new TextDecoder();
    const decodedMessage = dec.decode(decrypted);
    return decodedMessage;
  }

  private ab2str(buf) {
    return String.fromCharCode.apply(null, new Uint8Array(buf));
  }

  private str2ab(str) {
    const buf = new ArrayBuffer(str.length);
    const bufView = new Uint8Array(buf);
    for (let i = 0, strLen = str.length; i < strLen; i++) {
      bufView[i] = str.charCodeAt(i);
    }
    return buf;
  }
}

The java code to convert the string to PublicKey Object

String pubKey = loginRequest.publicKey;
        PublicKey pk = null;
        try {
           
            byte[] keyBytes = Base64.decodeBase64(pubKey);
            X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            pk = kf.generatePublic(spec);
        } catch (Exception e) {
            System.out.println("Exception in generating primary key: " + e.getMessage());
        }

Encrypting the string with the publicKey

 public static byte[] encrypt(String text, PublicKey key) {
        byte[] cipherText = null;
        try {
            // get an RSA cipher object and print the provider
            final Cipher cipher = Cipher.getInstance(ALGORITHM);
            OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), PSource.PSpecified.DEFAULT);
            // encrypt the plain text using the public key
            cipher.init(Cipher.ENCRYPT_MODE, key, oaepParams);
            cipherText = cipher.doFinal(text.getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return cipherText;
    }

I get back an encrypted string when when I try to decode it in Javascript I get an error. Any idea what I need to change in my code to fix this?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神解答

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...