【问题标题】:Light weight api to read PKCS#1 RSA public key in java?在java中读取PKCS#1 RSA公钥的轻量级api?
【发布时间】:2015-02-22 23:08:38
【问题描述】:

我使用 bouncycastle 读取 PKCS#1 格式的 RSA 公钥,该密钥以:

-----BEGIN RSA PUBLIC KEY---- 

代码运行良好,但它依赖于一个沉重的 bouncycastle jar。会导致代码无法在Android上编译,因为java函数的个数超过65535。

我已将 bouncycastle 更改为 spongycastle 并将 prov.jar 和 pkix.jar 解耦。也只使用一个类来减少代码引用:

org.spongycastle.asn1.pkcs.RSAPublicKey rsaPublicKey = org.spongycastle.asn1.pkcs.RSAPublicKey.getInstance(keyBytes);

但是 classes.dex 仍然会大 2MB。

所以我正在查找是否有轻量级 api 可以做到这一点?或者读取PKCS#1 RSA公钥的算法会很容易写?

附:使用 Proguard 根本无法解决问题,它会禁用 IDE 中的调试器。

【问题讨论】:

  • 有这么多限制,为什么不自己写呢?应该不会太难。

标签: java android rsa pkcs#1


【解决方案1】:

这是我快速编写的一些代码,显示了这是多么容易。使用久经考验的库肯定会更好,但这个特殊的 ASN.1 对象相对简单:

import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Paths;


public class ParseRSAPublicKey {
    private static final int SEQUENCE = 0x30;
    private static final int INTEGER = 0x02;
    private final ByteBuffer derBuf;

    public ParseRSAPublicKey(byte[] der) {
        derBuf = ByteBuffer.wrap(der);
    }

    public byte get() {
        return derBuf.get();
    }

    /**
     * @return the next byte of the buffer as an int
     */
    public int getAsInt() {
        return get() & 0xff;
    }

    public byte[] getArray(int len) {
        byte [] arr = new byte[len];
        derBuf.get(arr);
        return arr;
    }

    public int parseId() {
        // Only the low-tag form is legal.
        int idOctect = getAsInt();
        if (idOctect >= 0x31) {
            throw new RuntimeException("Invalid identifier octets");
        }
        return idOctect;        
    }

    public long parseLength() {
        int octet1 = getAsInt();
        if (octet1 < 128) {
            // short form of length
            return octet1;
        } else {
            // long form of length
            int lengthOfLength = octet1 & 0x7f;
            BigInteger bigLen = new BigInteger(1, getArray(lengthOfLength));

            if (bigLen.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0){
                throw new RuntimeException("Length is too long");
            }
            return bigLen.longValue();
        }
    }

    public BigInteger parseInteger() {
        if (parseId() != INTEGER) {
            throw new RuntimeException("expected SEQUENCE tag");
        }

        long length = parseLength();
        if (length > Integer.MAX_VALUE){
            throw new RuntimeException("Length is too long");
        }
        return new BigInteger(1, getArray((int) length));
    }
    public BigInteger[] parse() {
        // Parse SEQUENCE header
        if (parseId() != SEQUENCE) {
            throw new RuntimeException("expected SEQUENCE tag");
        }

        @SuppressWarnings("unused")
        long seqLength = parseLength(); // We ignore this

        // Parse INTEGER modulus
        BigInteger n = parseInteger();
        BigInteger e = parseInteger();
        return new BigInteger[] {n, e};

    }

    public static void main(String [] args) throws Exception {
        byte [] der = Files.readAllBytes(Paths.get("rsapub.p1"));
        ParseRSAPublicKey parser = new ParseRSAPublicKey(der);
        BigInteger [] results = parser.parse();
        System.out.printf("%d%n", results[0]);
        System.out.printf("%d%n", results[1]);
    }
}

【讨论】:

  • 是的,我知道很简单,但是我的代码是用于业务开发的,所以我需要稳定的代码:-)
猜你喜欢
  • 2012-05-21
  • 2011-11-28
  • 2017-10-14
  • 2019-06-11
  • 2010-11-19
  • 2021-06-22
  • 1970-01-01
  • 2019-01-13
  • 2018-08-04
相关资源
最近更新 更多