Skip to content
This repository has been archived by the owner on Apr 25, 2022. It is now read-only.

老铁,还得麻烦看看,uniapp公钥加密,服务端[php]对应私钥解密,无法解密 #7

Closed
by-addy opened this issue Dec 22, 2019 · 5 comments

Comments

@by-addy
Copy link

by-addy commented Dec 22, 2019

uniapp端使用私钥加密,服务端[php]使用对应公钥解密,正常
服务端[php]使用私钥加密,uniapp端公钥钥解密,也正常

        /**
	 * 字符串RSA加密
	 * @param uncrypted
	 * @param keys
	 * @param digest base64\buffer|binary|hex
	 * @returns {*}
	 */
	rsaEncrypt(uncrypted, keys, digest = 'base64') {
		let rsa = new Signature.RSA(); // RSA对象
		// 使用私钥加密
		rsa.setPrivateKey(keys.privateKey);
		let encrypted = rsa.keys.encryptPrivate(uncrypted, 'base64');
		console.log('encrypted', encrypted);
		return encrypted;
	}

	/**
	 * 字符串RSA解密
	 * @param encrypted
	 * @param keys
	 */
	rsaDecrypt(encrypted, keys) {
		let rsa = new Signature.RSA(); // RSA对象
		// 使用公钥解密
		rsa.setPublicKey(keys.publicKey);
		let decrypted = rsa.keys.decryptPublic(encrypted, 'utf8');
		// console.log('decrypted', decrypted);
		return decrypted;
	}

但是如果:
uniapp端使用公钥加密,服务端[php]使用对应私钥解密,无法解密
服务端[php]使用公钥加密,uniapp端使用私钥解密,也无法解密

        /**
	 * 字符串RSA加密
	 * @param uncrypted
	 * @param keys
	 * @param digest base64\buffer|binary|hex
	 * @returns {*}
	 */
	rsaEncrypt(uncrypted, keys, digest = 'base64') {
		let rsa = new Signature.RSA(); // RSA对象

		//使用公钥加密,对方使用私钥解密
		rsa.setPublicKey(keys.publicKey);
	        let encrypted = rsa.encrypt(uncrypted, digest);
		console.log('uncrypted', rsa, uncrypted, keys.publicKey, digest);
		
		return encrypted;
	}

	/**
	 * 字符串RSA解密
	 * @param encrypted
	 * @param keys
	 */
	rsaDecrypt(encrypted, keys) {
		let rsa = new Signature.RSA(); // RSA对象

		// 使用私钥解密
		rsa.setPrivateKey(keys.privateKey);
		let decrypted = rsa.decrypt(encrypted, 'utf8');
		return decrypted;
	}

这是我服务端的代码

/**
     * 私钥加密
     *
     * @param $data
     * @param $rsaPrivateKey
     *
     * @return string
     */
    public static function privateKeyEncode($data, $rsaPrivateKey)
    {
        $encrypted   = '';
        $private_key = openssl_pkey_get_private($rsaPrivateKey);
        if ($private_key)
            openssl_private_encrypt($data, $encrypted, $private_key); //私钥加密
        return base64_encode($encrypted);
    }

    /**
     * 公钥加密
     *
     * @param $data
     * @param $rsaPublicKey
     *
     * @return string
     */
    public static function publicKeyEncode($data, $rsaPublicKey)
    {
        $encrypted  = '';
        $public_key = openssl_pkey_get_public($rsaPublicKey);
        if ($public_key)
            openssl_public_encrypt($data, $encrypted, $public_key); //私钥加密
        return base64_encode($encrypted);
    }

    /**
     * 用公钥解密私钥加密内容
     *
     * @param $data
     * @param $rsaPublicKey
     *
     * @return string
     */
    public static function decodePrivateEncode($data, $rsaPublicKey)
    {
        $decrypted  = '';
        $public_key = openssl_pkey_get_public($rsaPublicKey);

        if ($public_key)
            openssl_public_decrypt(base64_decode($data), $decrypted, $public_key); //私钥加密的内容通过公钥可用解密出来
        return $decrypted;
    }

    /**
     * 用私钥解密公钥加密内容
     *
     * @param $data
     * @param $rsaPrivateKey
     *
     * @return string
     */
    public static function decodePublicEncode($data, $rsaPrivateKey)
    {
        $decrypted   = '';
        $private_key = openssl_pkey_get_private($rsaPrivateKey);
        if ($private_key)
            openssl_private_decrypt(base64_decode($data), $decrypted, $private_key); //私钥解密
        return $decrypted;
    }

也就是说换一下,就不行了,
但是在各自,自己加密,然后自己解密是可以的。
确定是测试过很多次的,就是不行,换成,私钥加密,公钥解密相互都是可以的,😰,麻烦老哥给看看
是不是编码什么的问题?

@lipingruan
Copy link
Owner

lipingruan commented Dec 22, 2019

一般来说加解密没通过的原因都是:

  1. 公私钥不匹配
  2. 编码格式不统一
  3. 密钥格式不统一
  4. 填充方式不统一

根据以上几个原因分析:

  1. 略过
  2. 编码肯定是统一的, UTF-8
  3. 密钥格式肯定是统一的, 都是 PKCS#8 格式
  4. 填充方式你没传值, 使用的是 PHP 默认值 PKCS1_PADDING, 这里和 JS 端没统一, JS 端默认是 PKCS1_OAEPPadding, 你要么改 JS 端要么改 PHP 端.
    JS 端更改与 PHP 端默认统一的填充方式:
    rsa.keys.setOptions({encryptionScheme: 'pkcs1'});
    PHP 端更改与 JS 端默认统一的填充方式:
    openssl_public_encrypt 方法第 4 个参数传 OPENSSL_PKCS1_OAEP_PADDING

@by-addy
Copy link
Author

by-addy commented Dec 23, 2019

一般来说加解密没通过的原因都是:

  1. 公私钥不匹配
  2. 编码格式不统一
  3. 密钥格式不统一
  4. 填充方式不统一

根据以上几个原因分析:

  1. 略过
  2. 编码肯定是统一的, UTF-8
  3. 密钥格式肯定是统一的, 都是 PKCS#8 格式
  4. 填充方式你没传值, 使用的是 PHP 默认值 PKCS1_PADDING, 这里和 JS 端没统一, JS 端默认是 PKCS1_OAEPPadding, 你要么改 JS 端要么改 PHP 端.
    JS 端更改与 PHP 端默认统一的填充方式:
    rsa.keys.setOptions({encryptionScheme: 'pkcs1'});
    PHP 端更改与 JS 端默认统一的填充方式:
    openssl_public_encrypt 方法第 4 个参数传 OPENSSL_PKCS1_OAEP_PADDING
  1. ok
    2.ok
    3.ok
    4.这个有点奇怪,用私钥加密,公钥解密就正常了,难道这样时填充方式就一样了吗?里面是不是存在一点问题呢

@lipingruan
Copy link
Owner

OpenSSL 使用私钥加密时只支持:

  1. PKCS1_PADDING
  2. NO_PADDING

排除不安全的 NO_PADDING, 私钥加密都是使用 PKCS1_PADDING

@lipingruan
Copy link
Owner

@zd520ll 老铁问题解决了吗?

@by-addy
Copy link
Author

by-addy commented Dec 26, 2019

已解决,谢谢

@by-addy by-addy closed this as completed Dec 26, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants