手动从(RSA)公钥创建JWK

12

我需要将RSA PublicKey转换为有效的JWK。特别是JWK的“n”和“e”值是我遇到困难的地方。当查看示例JWK时,编码似乎不正确,请参考https://www.rfc-editor.org/rfc/rfc7517#page-25

目前,我的代码基本上看起来是这样的:

private Map<String, Object> generateJWK(PublicKey publicKey){

    RSAPublicKey rsa = (RSAPublicKey) publicKey;

    Map<String, Object> values = new HashMap<>();

    values.put("kty", rsa.getAlgorithm()); // getAlgorithm() returns kty not algorithm
    values.put("kid", "someuniqueid");
    values.put("n", Base64.encode(rsa.getModulus().toString()));
    values.put("e", Base64.encode(rsa.getPublicExponent().toString()));
    values.put("alg", "RS256");
    values.put("use", "sig");

    return values;
}

然而,输出似乎没有正确编码或其他原因,例如 e 看起来像这样:NjU1Mzc=

n 不包含像 -_+ 这样的特殊字符。

jMzk1MNT0xTk2NED1xzzgNyQ00IykADzMAM0c0wz0M0MONj2z5TgNzI3yAM0OONYzzMjzwNzDxgAzxDxzMMAjTwNNDYMINMgNQDOEAkIM2jMQzkjUTDUYONNg1A00Tw1Nx4YEzAzjUT1MTNMjDjMM1MNNAjyTMIzxNADDINQANwT5yTDEMjEzNz2z2gOgjDDDNyNDjTzz43ETOYMI35gDjE00MYYM2DzDjDgww53Mwz0ME1NMgOM3MIzYTzMwzOMIQU5MjOzUjMNQNNg50U5NIDNzw2DMMOggNcQQM21TI5NMzDTN5Mj123O33MNNMkyNTNONxMM5wMMc04jTgAUE3MM1zMg4NNMT4MNDMM5yTO2j4jNDEMy1yNANNAzOIEUDzNwzExwTIkNjUjkN54Uz0DT5x0zM51k2MxYkx0zMNzxMkDUDTTQN3gAYODATQDDwMDMjMMcONjxMNTYMT5kgxNkMjNMQU0jzMEwIIMzTzUD4MgYDkDNzcAzN0TN4yNTz11DMxDUjDM2MyDMy4DEINMwT22QxjNNEzNDATy1OM1NNDxYgz5TxDkj3gQ32kIwNNkDO3xczDAENcTMNO0MOjTDwE3g11wNUcgNTwQk30kjjNNzTz4jTj4OOjQNYzMzcMjTQMkyzNNNUQOTOMMkMMMNzwNxDOEkg4xADIT4DNxMz2TENT4yN4z2I2zjyMU3DTOEQN4MIQjNDMU5Y11QkccwMNI0kNzyNjMMN4NMTTNMzMwxMjjDzgAANO1zwjYIEUjM1ADgDNjxTITMNNkIYxzyzzEEDMzDzNjzM4NjNNjc3ITTD0T5jzN=

我是否正确地假设了值n和e都没有得到适当的编码? 我应该如何将PublicKey转换为JWK?(不能使用第三方库)

2个回答

18

JWK使用 base64url 编码,该编码方式与 base64 略有不同。此外,请不要对 BigInteger 值使用 toString() 方法。直接将数据作为字节数组获取。

Base64.encode(rsa.getModulus().toString())
Base64.encode(rsa.getPublicExponent().toString())

关于

Base64.getUrlEncoder().encodeToString(rsa.getModulus().toByteArray())
Base64.getUrlEncoder().encodeToString(rsa.getPublicExponent().toByteArray())

0

以下代码运行良好,使用Apache Base64,按短语搜索

RFC 4648与RFC 2045编解码的区别

以及

将Java BigInteger转换为字节数组时,前导零

private static byte[] toByteArray(BigInteger bigInteger)
    {
        byte[] bytes = bigInteger.toByteArray();
        byte[] result;
        if ((bigInteger.bitLength() % 8 == 0) && (bytes[0] == 0) && bytes.length > 1)
        {
            result = new byte[bytes.length - 1];
            System.arraycopy(bytes, 1, result, 0, result.length);
        }
        else {result = bytes;}
        return result;
    }
...
import org.apache.commons.codec.binary.Base64;
...
jwk.put("n", Base64.encodeBase64URLSafeString(toByteArray(publicKey.getModulus()) ) );
jwk.put("e", Base64.encodeBase64URLSafeString(publicKey.getPublicExponent().toByteArray()) );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接