请问一下这个 RSA 密钥经过了怎么处理呀

2021-10-10 17:15:13 +08:00
 kangsgo

他给了我一个测试公钥

MIGAMA0GCSqGSIb3DQEBAQUAA28AMGwCZQCeh0LCZFTcyDINybUavJb-d0sMTMv5-xGDcGmJq38cwtij3n-bFl_qpX2lgN516bGnqZC0-kt-RkmWitXSNj-1yLu4hg1SNy-HfHuvFWulDLpDgt-JOflfCH9cMUZxbOWhf6IlAgMBAAE

不知道经过了什么,我用 php 怎么都读不了这个公钥

下面是文档里面给的 java demo,一直转不成 php 版本的

package com.xxtx.common.util;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;


public class RSAUtils {
public static final String CHARSET = "UTF-8";
    public static final String RSA_ALGORITHM = "RSA"; // ALGORITHM ['?lg?r??(?)m] 算法的意思

public static Map<String, String>createKeys(int keySize) {
// 为 RSA 算法创建一个 KeyPairGenerator 对象
KeyPairGenerator kpg;
        try {
            kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
} catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException("No such algorithm-->["+ RSA_ALGORITHM + "]");
}

// 初始化 KeyPairGenerator 对象,密钥长度
kpg.initialize(keySize);
// 生成密匙对
KeyPair keyPair = kpg.generateKeyPair();
// 得到公钥
Key publicKey = keyPair.getPublic();
String publicKeyStr = Base64.encodeBase64URLSafeString(publicKey.getEncoded());
// 得到私钥
Key privateKey = keyPair.getPrivate();
String privateKeyStr = Base64.encodeBase64URLSafeString(privateKey.getEncoded());
// map 装载公钥和私钥
Map<String, String> keyPairMap = new HashMap<String, String>();
keyPairMap.put("publicKey", publicKeyStr);
keyPairMap.put("privateKey", privateKeyStr);
// 返回 map
return keyPairMap;
}

/**
     * 得到公钥
* @param publicKey  密钥字符串(经过 base64 编码)
* @throws Exception
     */
public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
// 通过 X509 编码的 Key 指令获得公钥对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
        return key;
}

/**
     * 得到私钥
* @param privateKey  密钥字符串(经过 base64 编码)
* @throws Exception
     */
public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
// 通过 PKCS#8 编码的 Key 指令获得私钥对象
KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
        return key;
}

/**
     * 公钥加密
* @param data
* @param publicKey
* @return
*/
public static String publicEncrypt(String data, RSAPublicKey publicKey) {
try {
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), publicKey.getModulus().bitLength()));
} catch (Exception e) {
throw new RuntimeException("加密字符串["+ data + "]时遇到异常", e);
}
    }

/**
     * 私钥解密
* @param data
* @param privateKey
* @return
*/

public static String privateDecrypt(String data, RSAPrivateKey privateKey) {
try {
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), privateKey.getModulus().bitLength()), CHARSET);
} catch (Exception e) {
throw new RuntimeException("解密字符串["+ data + "]时遇到异常", e);
}
    }

/**
     * 私钥加密
* @param data
* @param privateKey
* @return
*/

public static String privateEncrypt(String data, RSAPrivateKey privateKey) {
try {
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
//每个 Cipher 初始化方法使用一个模式参数 opmod,并用此模式初始化 Cipher 对象。此外还有其他参数,包括密钥 key 、包含密钥的证书 certificate 、算法参数 params 和随机源 random 。
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            return Base64.encodeBase64URLSafeString(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes(CHARSET), privateKey.getModulus().bitLength()));
} catch (Exception e) {
throw new RuntimeException("加密字符串["+ data + "]时遇到异常", e);
}
    }

/**
     * 公钥解密
* @param data
* @param publicKey
* @return
*/

public static String publicDecrypt(String data, RSAPublicKey publicKey) {
try {
            Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, publicKey);
            return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), CHARSET);
} catch (Exception e) {
throw new RuntimeException("解密字符串["+ data + "]时遇到异常", e);
}
    }

//rsa 切割解码  , ENCRYPT_MODE,加密数据   ,DECRYPT_MODE,解密数据
private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize) {
int maxBlock = 0;  //最大块
if (opmode == Cipher.DECRYPT_MODE) {
            maxBlock = keySize / 8;
} else {
            maxBlock = keySize / 8 - 11;
}
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] buff;
        int i = 0;
        try {
while (datas.length > offSet) {
if (datas.length - offSet > maxBlock) {
//可以调用以下的 doFinal ()方法完成加密或解密数据:
buff = cipher.doFinal(datas, offSet, maxBlock);
} else {
                    buff = cipher.doFinal(datas, offSet, datas.length - offSet);
}
                out.write(buff, 0, buff.length);
i++;
offSet = i * maxBlock;
}
        } catch (Exception e) {
throw new RuntimeException("加解密阀值为["+ maxBlock + "]的数据时发生异常", e);
}
byte[] resultDatas = out.toByteArray();
IOUtils.closeQuietly(out);
        return resultDatas;
}


}
2279 次点击
所在节点    Java
10 条回复
kangsgo
2021-10-10 17:16:53 +08:00
我试了一下 base64 解密这个公钥,好像也解密不出来
sujin190
2021-10-10 18:25:00 +08:00
自己组一下 pem 文件格式呗,网上查一下就有吧,php 好像读取的是这种格式吧,确实是不需要自己解码 base64 的
keyfunc
2021-10-10 18:27:27 +08:00
kangsgo
2021-10-10 18:41:25 +08:00
@sujin190 他给的公钥是处理过的,不知道处理了哪里,php 读不出来
kangsgo
2021-10-10 18:43:27 +08:00
@keyfunc 您好,请问方便多指导一下么,这个做的公钥还是没法加密,我用的这个在线加密的
https://www.bejson.com/enc/rsa/
eason1874
2021-10-10 18:46:50 +08:00
因为这个不是标准的 base64,需要先转换成标准 base64,看你这么久没解决,给你写个例子

```
<?php
$str = 'MIGAMA0GCSqGSIb3DQEBAQUAA28AMGwCZQCeh0LCZFTcyDINybUavJb-d0sMTMv5-xGDcGmJq38cwtij3n-bFl_qpX2lgN516bGnqZC0-kt-RkmWitXSNj-1yLu4hg1SNy-HfHuvFWulDLpDgt-JOflfCH9cMUZxbOWhf6IlAgMBAAE';

function urlsafe_b64decode($string) {
$data = str_replace(array('-','_'),array('+','/'),$string);
$mod4 = strlen($data) % 4;
if ($mod4) {
$data .= substr('====', $mod4);
}
return base64_decode($data);
}

// 转为标准 base64
$str = urlsafe_b64decode($str);

// 封装
$pub_key = "-----BEGIN PUBLIC KEY-----\n" . base64_encode($str) . "\n-----END PUBLIC KEY-----";

// 解析证书,用于后续加解密等操作
$pub_key_res = openssl_get_publickey($pub_key);

// 读取证书信息
var_dump(openssl_pkey_get_details($pub_key_res));

// 加密例子,输出 base64 格式
openssl_public_encrypt("hello", $crypttext, $pub_key);
var_dump(base64_encode($crypttext));

```
sarvatathagata
2021-10-10 18:49:29 +08:00
这代码挺有意思的啊

"// ALGORITHM ['?lg?r??(?)m] 算法的意思"
“阀值”
eason1874
2021-10-10 18:56:15 +08:00
顺便一提,处理 base64 内容,第一件事先看格式对不对,很多接受 base64 格式的输入只能接受标准 base64

标准 base64 只有 + / = 三个符号,有 - _ 这种符号的是 base64 变体,通常用来兼容 URL,因为默认符号作为网址时被转义
kangsgo
2021-10-11 10:04:25 +08:00
@eason1874 谢谢大佬,能否给个联系方式,不问问题哈,仅发红包表示感谢
eason1874
2021-10-11 11:08:42 +08:00
@kangsgo 不了,别客气。我是电脑摸鱼,方便,写个例子就几分钟的事。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/806864

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX