• Java & PHP RSA 互通密钥、签名、验签、加密、解密


    RSA加密算法是一种非对称加密算法。在公开密钥加密和电子商业中RSA被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。

    RSA是第一个比较完善的公开密钥算法,它既能用于加密,也能用于数字签名。这个算法经受住了多年深入的密码分析,虽然密码分析者既不能证明也不能否定RSA的安全性,但这恰恰说明该算法有一定的可信性,目前它已经成为最流行的公开密钥算法。

    RSA的安全基于大数分解的难度。其公钥和私钥是一对大素数(100到200位十进制数或更大)的函数。从一个公钥和密文恢复出明文的难度,等价于分解两个大素数之积(这是公认的数学难题)。

    RSA的公钥、私钥的组成,以及加密、解密的公式可见于下表:

    版本

    语言 版本
    PHP 7.3.11
    Java 1.8.0_231

    密钥生成

    PHP

    RSAUtils::resetGenKeyPair

    public static function resetGenKeyPair()
    {
    	$config = array(
    		"private_key_bits" => self::PRIVATE_KEY_BITS,
    		"private_key_type" => self::KEY_ALGORITHM,
    	);
    
    	$openssl = openssl_pkey_new($config);
    	openssl_pkey_export($openssl, $privateKey);
    	$publicKey = openssl_pkey_get_details($openssl);
    	$publicKey = $publicKey["key"];
    
    	return [
    		'publicKey'     => $publicKey,
    		'privateKey'    => $privateKey,
    		'publicKeyStr'  => self::key2str($publicKey),
    		'privateKeyStr' => self::key2str($privateKey)
    	];
    }
    

    Java

    RSAUtils.resetGenKeyPair

    static Map<String, Object> resetGenKeyPair() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
    
        KeyPair keyPair            = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey     = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey   = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<String, Object>(2);
    
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }
    

    签名

    私钥加签。

    有时签名可能会因为数据编码不同而导致不一致,所以要求 PHP 和 Java 都对数据进行编码处理。

    PHP

    RSAUtils::sign

    public static function sign($dataStr, $privateKey)
    {
        $dataStr = self::str2utf8($dataStr);
        $privateKeyId = openssl_get_privatekey($privateKey);
        openssl_sign($dataStr, $sign, $privateKeyId, self::SIGNATURE_ALGORITHM);
        openssl_free_key($privateKeyId);
        return base64_encode($sign);
    }
    

    Java

    RSAUtils.sign

    static String sign(String data, String privateKey) throws Exception {
        byte[] keyBytes = Base64.decode(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
    
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateK   = keyFactory.generatePrivate(pkcs8KeySpec);
        Signature signature   = Signature.getInstance(SIGNATURE_ALGORITHM);
    
        signature.initSign(privateK);
        signature.update(data.getBytes(ENCODING));
        return Base64.encodeToString(signature.sign());
    }
    

    验签

    公钥验签。

    PHP

    RSAUtils::verifySign

    public static function verifySign($dataStr, $publicKey, $sign)
    {
        $dataStr     = self::str2utf8($dataStr);
        $publicKeyId = openssl_get_publickey($publicKey);
        return (boolean) openssl_verify($dataStr, base64_decode($sign), $publicKeyId, self::SIGNATURE_ALGORITHM);
    }
    

    Java

    RSAUtils.verifySign

    static boolean verifySign(String data, String publicKey, String sign) throws Exception {
        try {
            byte[] keyBytes = Base64.decode(publicKey);
    
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory      = KeyFactory.getInstance(KEY_ALGORITHM);
            PublicKey publicK          = keyFactory.generatePublic(keySpec);
            Signature signature        = Signature.getInstance(SIGNATURE_ALGORITHM);
    
            signature.initVerify(publicK);
            signature.update(data.getBytes(ENCODING));
    
            return signature.verify(Base64.decode(sign));
        } catch (Exception e) {
            throw e;
        }
    }
    

    加密

    公钥加密

    PHP

    RSAUtils::encryptByPublicKey

    public static function encryptByPublicKey($dataStr, $publicKey)
    {
        $dataStr     = self::str2utf8($dataStr);
        $publicKeyId = openssl_get_publickey($publicKey);
        $data        = "";
    
        $dataArray = str_split($dataStr, self::PRIVATE_KEY_BITS / 8 - 11);
        foreach ($dataArray as $value) {
            openssl_public_encrypt($value,$encryptedTemp, $publicKeyId,self::EN_DE_ALGORITHM);
            $data .= $encryptedTemp;
        }
        openssl_free_key($publicKeyId);
        return base64_encode($data);
    }
    

    Java

    RSAUtils.encryptByPublicKey

    static String encryptByPublicKey(String dataStr, String publicKey) throws Exception {
        byte[] data     = dataStr.getBytes(ENCODING);
        byte[] keyBytes = Base64.decode(publicKey);
    
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK           = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher         = Cipher.getInstance(keyFactory.getAlgorithm());
    
        cipher.init(Cipher.ENCRYPT_MODE, publicK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
    
        int offSet = 0;
        byte[] cache;
        int i = 0;
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return Base64.encodeToString(encryptedData);
    }
    

    私钥加密

    PHP

    RSAUtils::encryptByPrivateKey

    public static function encryptByPrivateKey($dataStr, $privateKey)
    {
        $dataStr      = self::str2utf8($dataStr);
        $privateKeyId = openssl_get_privatekey($privateKey);
        $data         = "";
    
        $dataArray = str_split($dataStr, self::PRIVATE_KEY_BITS / 8 - 11);
        foreach ($dataArray as $value) {
            openssl_private_encrypt($value,$encryptedTemp, $privateKeyId,self::EN_DE_ALGORITHM);
            $data .= $encryptedTemp;
        }
        openssl_free_key($privateKeyId);
        return base64_encode($data);
    }
    

    Java

    RSAUtils.encryptByPrivateKey

    static String encryptByPrivateKey(String dataStr, String privateKey) throws Exception {
        byte[] data     = dataStr.getBytes(ENCODING);
        byte[] keyBytes = Base64.decode(privateKey);
    
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK          = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher         = Cipher.getInstance(keyFactory.getAlgorithm());
    
        cipher.init(Cipher.ENCRYPT_MODE, privateK);
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
    
        int offSet = 0;
        byte[] cache;
        int i = 0;
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();
        return Base64.encodeToString(encryptedData);
    }
    

    解密

    公钥解密

    PHP

    RSAUtils::decryptByPublicKey

    public static function decryptByPublicKey($encryptData, $publicKey) {
        $decrypted   = "";
        $decodeStr   = base64_decode($encryptData);
        $publicKeyId = openssl_get_publickey($publicKey);
    
        $enArray = str_split($decodeStr, self::PRIVATE_KEY_BITS / 8);
    
        foreach ($enArray as $value) {
            openssl_public_decrypt($value,$decryptedTemp, $publicKeyId,self::EN_DE_ALGORITHM);
            $decrypted .= $decryptedTemp;
        }
        openssl_free_key($publicKeyId);
        return $decrypted;
    }
    

    Java

    RSAUtils.decryptByPublicKey

    static String decryptByPublicKey(String encryptedDataStr, String publicKey) throws Exception {
        byte[] encryptedData = Base64.decode(encryptedDataStr);
        byte[] keyBytes      = Base64.decode(publicKey);
    
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicK = keyFactory.generatePublic(x509KeySpec);
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    
        cipher.init(Cipher.DECRYPT_MODE, publicK);
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
    
        int offSet = 0;
        byte[] cache;
        int i = 0;
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return new String(decryptedData, ENCODING);
    }
    

    私钥解密

    PHP

    RSAUtils::decryptByPrivateKey

    public static function decryptByPrivateKey($encryptData, $private) {
        $decrypted    = "";
        $decodeStr    = base64_decode($encryptData);
        $privateKeyId = openssl_get_privatekey($private);
    
        $enArray = str_split($decodeStr, self::PRIVATE_KEY_BITS / 8);
    
        foreach ($enArray as $value) {
            openssl_private_decrypt($value,$decryptedTemp, $privateKeyId,self::EN_DE_ALGORITHM);
            $decrypted .= $decryptedTemp;
        }
        openssl_free_key($privateKeyId);
        return $decrypted;
    }
    

    Java

    RSAUtils.decryptByPrivateKey

    static String decryptByPrivateKey(String encryptedDataStr, String privateKey) throws Exception {
        byte[] encryptedData = Base64.decode(encryptedDataStr);
        byte[] keyBytes      = Base64.decode(privateKey);
    
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key privateK          = keyFactory.generatePrivate(pkcs8KeySpec);
        Cipher cipher         = Cipher.getInstance(keyFactory.getAlgorithm());
    
        cipher.init(Cipher.DECRYPT_MODE, privateK);
        int inputLen = encryptedData.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
    
        int offSet = 0;
        byte[] cache;
        int i = 0;
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_DECRYPT_BLOCK;
        }
        byte[] decryptedData = out.toByteArray();
        out.close();
        return new String(decryptedData, ENCODING);
    }
    

    Demo

    完整 Demo 源码:BNDong/demo/PhpJavaRsa

  • 相关阅读:
    四种访问权限修饰符的区别
    安全框架Shiro和Spring Security比较
    POJ 1873 The Fortified Forest 凸包 二进制枚举
    POJ 2007 Scrambled Polygon 极角排序
    POJ 1113 Wall 凸包
    hdu 2276 Kiki & Little Kiki 2 矩阵快速幂
    UVA 10689 Yet another Number Sequence 矩阵快速幂 水呀水
    UVa 10655 Contemplation! Algebra 矩阵快速幂
    直线与直线相交 直线与线段相交 线段与线段相交
    hdu 4686 Arc of Dream 自己推 矩阵快速幂
  • 原文地址:https://www.cnblogs.com/bndong/p/11842135.html
Copyright © 2020-2023  润新知