Java异常:不恰当的密钥规范和DER长度的简短读取

时间:2018-04-08 23:43:52

标签: java dsa apache-commons-codec

使用Apache Commons API中的Base64函数并使用DSA我试图从文件中加载基本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解码任何输入。

1 个答案:

答案 0 :(得分:1)

Java InputStream.available() is never guaranteed to tell you how much (more) data exists

  

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

in this commons-codec case it doesn't even try

  

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

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