【问题标题】:Read public key from file从文件中读取公钥
【发布时间】:2016-03-08 05:22:59
【问题描述】:

我正在尝试使用我的 java 程序验证文件。我不知道我做错了什么,我找到的所有解决方案都不起作用。 这是我的代码:

public boolean pruefeSignatur(File file, File signatur, File publicKey) {
    boolean verifies = false;
    try {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        // encode public key bytes
        FileInputStream keyfis = new FileInputStream(publicKey);
        byte [] encKey = new byte[keyfis.available()];
        keyfis.read(encKey);
        keyfis.close();
        // key specification
        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);
        // conversion
        KeyFactory keyFactory = KeyFactory.getInstance(pubKeySpec.getFormat());
        // generate publicKey
        PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
        // input signature bytes
        FileInputStream sigfis = new FileInputStream(signatur);
        byte[] sigToVerify = new byte[sigfis.available()];
        sigfis.read(sigToVerify);
        sigfis.close();
        // initialize the signature
        Signature sig = Signature.getInstance("RSA");
        sig.initVerify(pubKey);
        // supply signature object with the data to be verified
        FileInputStream datafis = new FileInputStream(file);
        BufferedInputStream bufin = new BufferedInputStream(datafis);
        byte[] buffer = new byte[1024];
        int len;
        while(bufin.available() != 0) {
            len = bufin.read(buffer);
            sig.update(buffer, 0, len);
        }
        bufin.close();
        //verify signature
        verifies = sig.verify(sigToVerify);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return verifies;
}

使用此代码,我得到了异常: java.security.spec.InvalidKeySpecException: java.lang.ClassCastException: org.bouncycastle.asn1.DERUnknownTag 无法转换为 org.bouncycastle.asn1.ASN1Object

当我使用Base64时,例如:

        Base64 decoder = new Base64();
        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(decoder.decode(encKey));

我得到了例外: java.security.spec.InvalidKeySpecException: java.io.IOException: 意外的内容结束标记

我发现的另一个解决方案是将其更改为:

        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);
        // conversion
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

但后来我得到了例外: java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: 无效的密钥格式

我用 Gpg4win 和 Kleopatra 制作了我的钥匙。

编辑: 现在我没有收到错误,但函数总是返回 false。所以我不确定一切是否正确。

public boolean pruefeSignatur(File file, File signaturFile, File publicKeyFile) throws IOException {
    boolean verifies = false;
    FileInputStream keyfis = null;
    DataInputStream keydis = null;
    FileInputStream sigfis = null;
    DataInputStream sigdis = null;
    FileInputStream datafis = null;
    DataInputStream datadis = null;
    try {
        // add provider
        Security.addProvider(new BouncyCastleProvider());

        // encode public key bytes
        keyfis = new FileInputStream(publicKeyFile);
        keydis = new DataInputStream(keyfis);
        byte[] keyBytes = new byte[(int) publicKeyFile.length()];
        keydis.readFully(keyBytes);
        keyfis.close();
        keydis.close();

        // key specification
        String modulusBase64 = new String(keyBytes);
        Base64 b64 = new Base64();
        String exponentBase64 = "65337"; //festgelegte Zahl http://crypto.stackexchange.com/questions/3110/impacts-of-not-using-rsa-exponent-of-65537
        RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(1, b64.decode(modulusBase64)), new BigInteger(1, b64.decode(exponentBase64)));

        // conversion
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");

        // generate publicKey
        PublicKey publicKey = keyFactory.generatePublic(pubKeySpec);

        // read signature
        sigfis = new FileInputStream(signaturFile);
        sigdis = new DataInputStream(sigfis);
        byte[] sigBytes = new byte[(int) signaturFile.length()];
        sigdis.readFully(sigBytes);
        sigfis.close();
        sigdis.close();

        // initialize the signature
        Signature sig = Signature.getInstance("RSA");
        sig.initVerify(publicKey);

        // supply signature object with the data to be verified
        datafis = new FileInputStream(file);
        datadis = new DataInputStream(datafis);
        byte[] dataBytes = new byte[(int) file.length()];
        datadis.readFully(dataBytes);
        /*
        int len;
        while(datadis.available() != 0) {
            len = datadis.read(dataBytes);
            sig.update(dataBytes, 0, len);
        }
        */
        datadis.close();
        datafis.close();
        sig.update(dataBytes);

        //verify signature
        verifies = sig.verify(sigBytes);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (keyfis != null) {
            keyfis.close();
        }
        if (keydis != null) {
            keydis.close();
        }
        if (sigfis != null) {
            sigfis.close();
        }
        if (sigdis != null) {
            sigdis.close();
        }
        if (datafis != null) {
            datafis.close();
        }
        if (datadis != null) {
            datadis.close();
        }
    }
    return verifies;
}

【问题讨论】:

    标签: java key public


    【解决方案1】:

    终于有办法了:

        InputStream inSig = PGPUtil.getDecoderStream(new FileInputStream(signaturFile));
        //ArmoredInputStream inSig = new ArmoredInputStream(new FileInputStream(signaturFile));
        JcaPGPObjectFactory objFactory = new JcaPGPObjectFactory(inSig);
        PGPSignatureList signatureList = (PGPSignatureList) objFactory.nextObject();
        PGPSignature signature = signatureList.get(0);
    
        InputStream keyIn = PGPUtil.getDecoderStream(new FileInputStream(publicKeyFile));
        //ArmoredInputStream keyIn = new ArmoredInputStream(new FileInputStream(publicKeyFile));
        JcaPGPPublicKeyRingCollection pgpRing = new JcaPGPPublicKeyRingCollection(keyIn);
        PGPPublicKey publicKey = pgpRing.getPublicKey(signature.getKeyID());
    
        byte[] bytePublicKeyFingerprint = publicKey.getFingerprint();
        char[] publicKeyFingerprintHexArray = org.apache.commons.codec.binary.Hex.encodeHex(bytePublicKeyFingerprint);
        String publicKeyFingerprintHex = new String(publicKeyFingerprintHexArray);
    
        signature.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), publicKey);
    
        FileInputStream in = new FileInputStream(file);
        byte[] byteData = new byte[(int) file.length()];
        in.read(byteData);
        in.close();
        signature.update(byteData);
    
        if (signature.verify() && publicKeyFingerprintHex.equals(fingerprint)) {
            return true;
        } else {
            return false;
        }
    

    【讨论】:

      猜你喜欢
      • 2014-09-17
      • 2011-05-29
      • 2017-12-18
      • 2019-01-13
      • 2012-08-01
      • 1970-01-01
      • 2013-12-10
      • 2017-12-15
      相关资源
      最近更新 更多