0

使用来自 Apache Commons API 的 Base64 函数并使用 DSA 我正在尝试从文件中加载 base 64 编码的公钥,这是正在使用的方法

/**
 * Load a base-64 encoded public key in X.509 format
 * @param pkfile the name of the file containing the public key 
 * @return an instance of PublicKey on success or null on failure
 */
public PublicKey loadBase64PublicKey(String pkfile) { 
    PublicKey pub;
    Base64InputStream bis;
    byte[] buffer;

    // load the contents of the pkfile into the buffer
    try {
        bis = new Base64InputStream(new FileInputStream(pkfile));
        buffer = new byte[bis.available()];
        bis.read(buffer);
        bis.close();
    } catch (Exception e) {
        System.err.println(e.toString());
        return null;
    }

    // use a KeyFactory to parse the data
    try {
        KeyFactory kf = KeyFactory.getInstance("DSA");
        pub = kf.generatePublic(new X509EncodedKeySpec(buffer));
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }

    return pub;
}

主要方法:

public static void main(String args[]) {
    DigitalSignatureA DSA = new DigitalSignatureA();

    // load public key
    PublicKey pubKey;
    pubKey = DSA.loadBase64PublicKey("sign\\pubkey-1.dat");
}   

但是,当从 main 调用该方法时,会出现以下错误:

java.security.spec.InvalidKeySpecException: Inappropriate key specification: IOException: Short read of DER length
at sun.security.provider.DSAKeyFactory.engineGeneratePublic(Unknown Source)
at java.security.KeyFactory.generatePublic(Unknown Source)
at DigitalSignatureAssignment.loadBase64PublicKey(DigitalSignatureAssignment.java:147)
at DigitalSignatureAssignment.main(DigitalSignatureAssignment.java:224)

第 147 行将是pub = kf.generatePublic(new X509EncodedKeySpec(buffer)); 文件中的公钥以 X509 编码但保存在 base64 编码下,并且 Base64InputStream 解码任何输入。

4

1 回答 1

1

JavaInputStream.available()永远无法保证告诉您存在多少(更多)数据

请注意,虽然 InputStream 的某些实现会返回流中的字节总数,但许多不会。使用此方法的返回值来分配旨在保存此流中所有数据的缓冲区是不正确的。

在这个公共编解码器的情况下,它甚至没有尝试

返回:
如果 InputStream 已达到 EOF,则返回 0,否则返回 1

要么选择一个足够大的缓冲区大小开始,要么继续扩展它并阅读更多直到EOF,或者两者兼而有之。Files.readAllLines或者将文件作为文本(例如或在 j8+ 中)读入内存Files.readAllBytes,然后解码内存中的副本(FWIW j8+ 现在有java.util.Base64,你不需要 commons-codec)

于 2018-04-09T03:47:10.957 回答