简体   繁体   中英

symmetric and asymmetric encryption between Angular 2 and Spring Boot

I need send a password from Angular App to Spring boot backend and i need encrypt this password. I try to use AES to encrypt the password and RSA to encrypt the AES generated key, but i dont know how do this. My code: Angular 2 Side:

EncryptService:

public generateRandomKey( keyLength: number){
    let chars =
`0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmn
opqrstuvwxyz*&-%/!?*+=()`;
    let stringKey = "";
    for (let i=0; i < keyLength; i++) {
      var rnum = Math.floor(Math.random() * chars.length);
      stringKey += chars.substring(rnum,rnum+1);
    }

    return stringKey;

  }

  public aesEncrypt( phrase: string ){
    let key = this.generateRandomKey(50);
    let aesEncrypt = cryptojs.AES.encrypt(phrase, key);
    let aesKey = aesEncrypt.key
    let aesIv = aesEncrypt.iv;
    let encryptMessage = aesEncrypt.toString();

    return [encryptMessage, aesKey, aesIv];
  }


  public buildPubkFromPem( pem: string ){
    return forge.pki.publicKeyFromPem(pem);
  }

Component:

let pubKey = this.encryptService.buildPubkFromPem(environment.publicKey);
let data = this.encryptService.aesEncrypt(map.passwd);
let passwdEncrypt = data[0];
let aesKey = data[1];
let encryptAesKey = pubKey.encrypt(aesKey.toString());

      this.pendingRequestService
          .send({'passwd': passwdEncrypt, 'encryptAesKey': encryptAesKey)
          .finally(()=>{this.popupSignService.isLoading = false;})
          .subscribe( 
            result => {
              console.log("OK", result);
            }
        );
    }

Backend Side: Controller:

public ResponseEntity signDocs(
            @RequestParam(value = "passwd") String              passwd,
            @RequestParam(value = "encryptAesKey") String       encryptAesKey,
    ){

        try{
            signatureService.decryptMessage(passwd, encryptAesKey);
        }catch( Exception ex ){
            ex.printStackTrace();
        }

Service:

public String decryptMessage( String encrypMsg, String encryptAesKey ){

        // Load private key from P12
        ClassPathResource pkcs12     = new ClassPathResource("ssl/file.p12");
        KeyStore keystore = KeyStore.getInstance("PKCS12");
        keystore.load(pkcs12.getInputStream(), p12Password.toCharArray());
        String          alias   =   (String)keystore.aliases().nextElement();

        PrivateKey privateKey = (PrivateKey) keystore.getKey(alias, p12Password.toCharArray());

        // Decrypt
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.PRIVATE_KEY, privateKey);
        System.out.println(encryptAesKey);
        byte[] doFinal = cipher.doFinal(encryptAesKey.getBytes());
        String aesKey = new String(cipher.doFinal(Base64.decodeBase64(encryptAesKey)), "UTF-8");

        return aesKey;

    }

when i try to decrypt the AES encrypted key:

javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes

I think it's related when I encrypted the AES key. Can somebody help me? Thanks in advance.

EDIT

If i encrypt the string "Some text" with the public key using forge, and send the encrypted text to the backend does not work. If i ecrypt and decrypt using the same public and private key work from javascript to javascript and java to java. Javascript code:

let encryptedText = pubKey.encrypt(this.forgeService.encodeUTF8("Some text"));//<-- Encrypt "Some text"

I dont know if something is loosing (changing) when i send the encrypted text in the network.

I believe you have basic problem with encoding data (along others)

let encryptAesKey = pubKey.encrypt(aesKey.toString());

You are encrypting string representation of the key (not the key itself) and I believe JS returns the toString() in the hex format (please correct me if I am wrong). The result would be twice as long as the original key.

while i Java you are trying to decrypt the encrypted hex string rssulting in a byte array, which doesn't fit into expected 256 bit size

edit:

Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.PRIVATE_KEY, privateKey);

is wrong, you have to use Cipher. DECRYPT_MODE.

next :

String aesKey = new String(cipher.doFinal(.. DO NOT make a string from the key (encode when you want to print it), keep it as byte array. You are loosing nonprintable values.

you should be specific with the encryption mode

Cipher cipher = Cipher.getInstance("rsa/ecb/nopadding");

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