Angular 2和Spring Boot之间的对称和非对称加密

时间:2018-04-19 07:48:56

标签: javascript java angular spring-boot encryption

我需要从Angular App发送密码到Spring启动后端,我需要加密这个密码。我尝试使用AES加密密码和RSA加密AES生成的密钥,但我不知道如何做到这一点。 我的代码: 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);
  }

组件:

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);
            }
        );
    }

后端方面: 控制器:

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

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

服务:

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;

    }

当我尝试解密AES加密密钥时:

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

我认为加密AES密钥时它是相关的。 有人能帮助我吗? 提前谢谢。

修改

如果我使用伪造加密带有公钥的字符串“Some text”,并将加密文本发送到后端不起作用。如果我使用相同的公钥和私钥从javascript到javascript和java到java进行ecrypt和解密。 Javascript代码:

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

当我在网络中发送加密文本时,我不知道是否有东西丢失(改变)。

1 个答案:

答案 0 :(得分:0)

我相信你有编码数据的基本问题(和其他人一样)

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

你正在加密密钥的字符串表示(而不是密钥本身),我相信JS以十六进制格式返回toString()(如果我错了,请纠正我)。结果将是原始密钥的两倍。

而我是Java你试图在字节数组中解密加密的十六进制字符串rssulting,这不符合预期的256位大小

编辑:

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

错了,你必须使用Cipher。 DECRYPT_MODE。

下一个:

String aesKey = new String(cipher.doFinal(..不要从密钥中创建一个字符串(当你想打印它时进行编码),将其保存为字节数组。你正在失去不可打印的价值观。

您应该具体使用加密模式

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