首页 > 解决方案 > 如何读取 rsa 公钥形式的字符串(由 java 生成,我想用 Python 读取)

问题描述

生成公钥的代码是

    public static final String CHARSET = "UTF-8";
    public static final String RSA_ALGORITHM = "RSA";


    public static Map<String, String> createKeys(int keySize){
        KeyPairGenerator kpg;
        try{
            kpg = KeyPairGenerator.getInstance(RSA_ALGORITHM);
        }catch(NoSuchAlgorithmException e){
            throw new IllegalArgumentException("No such algorithm-->[" + RSA_ALGORITHM + "]");
        }

        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<String, String> keyPairMap = new HashMap<String, String>();
        keyPairMap.put("publicKey", publicKeyStr);
        keyPairMap.put("privateKey", privateKeyStr);

        return keyPairMap;
    }


    public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
        RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
        return key;
    }

然后将密钥发送给我,我想用 python importKey() 读取它。但我总是收到错误“不支持 RSA 密钥格式”。

The key is "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDGrLFBqubzi45M_yxs5Ps4XW3DIOeAo5x7Ca9EYmWAig3Rb3Efm2PCgipwNube2Ae5eUI5dYlQW32FSF81rw7vNdwfODDzITyWRPLEuVbBbkF5zD6kTxycqlVbH-uTyb95181jpY_XY6tmEOCZCq3mZhil9VA4ZvAoSBcJ8muXaQIDAQAB"

用谷歌搜索后,我尝试向它添加标题“-----BEGIN RSA PUBLIC KEY-----”,没有什么不同。

标签: javapython-3.xrsapublic-key-encryption

解决方案


  1. 您使用的是“URLsafe”base64 编码器,虽然不是标准的 Java 编码器。'URLsafe' 使用不同的字符(对于代码值 62 和 63)并且没有填充,也没有换行符。PEM 格式(早在 URLsafe 编码出现之前就设计了,实际上比 URL 存在早了一年多!)使用传统的 base64 字符(现在主要与 MIME 相关联)、填充和换行符(每 64 个字符)。尽管并非所有软件都检查换行符;你没有说你正在使用哪个 Python 加密库(有几个)所以我无法检查它是否关心这一点。

    在 Java 8 中,您可以使用Base64.getMimeEncoder()其中的大部分来处理这些问题,但是如果您被困在较旧的 Java(见下文)和/或其他一些库上,则必须提供有关它的详细信息。您可以- _字符转换为+ /,将=填充添加为 4 的倍数,并根据需要添加换行符。

    OTOH我看过的Python库接受'DER'(即二进制)以及PEM,所以你可以解码base64(许多解码器可以处理缺少填充,至少有些可以处理有或没有规范的两个字符集)并按原样使用。

  2. Java(它不精确地称为"X.509")以及 OpenSSL 和其他一些东西使用的公钥编码是通用的,并且包括算法标识符,因此正确的 PEM 标签是-----BEGIN PUBLIC KEY-----------END PUBLIC KEY-----(否RSA)。

  3. 你没有说你使用什么 Java,但它显然默认为 RSA 的 1024 位,这已经过时了好几年,并且不再被认为提供足够的安全余量(尽管还没有公开报告实际破坏) . 2048现在被广泛认为是最低限度,一些应用程序或环境由于各种原因使用更多。但是决定使用哪些加密参数(以及实际上您的应用程序是否应该使用 RSA,如果是的话,使用哪种变体)不是 SO 的编程问题和题外话;它们属于crypto.SX(用于基本原理)或security.SX(用于应用程序)。


推荐阅读