Verifying Signed Hash using Digital Signature
我正在实现一个以三件事为输入的接口
X509证书
用该证书的私钥签名的SignedHash
初始哈希
它必须执行以下操作:
我已实施以下验证数字签名的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | public static boolean verifySignedHash(String X509Certificate, String hash, String signedHash) { boolean isVerified = false; ByteArrayInputStream inputStream = null; ByteArrayOutputStream outputStream = null; ByteArrayOutputStream byo = null; try { outputStream = new ByteArrayOutputStream(); byte[] data = Base64.decodeBase64(X509Certificate); /* writing decoded X509 certificate to the ByteArrayOutputStream */ outputStream.write(data); byte[] inp = outputStream.toByteArray(); inputStream = new ByteArrayInputStream(inp); /* Getting the certificate from the Input */ CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate certs = (X509Certificate) cf .generateCertificate(inputStream); /* import encoded public key */ X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(certs .getPublicKey().getEncoded()); /* Instantiating KeyFactory for accesing the Keys as Object */ KeyFactory keyFactory = KeyFactory.getInstance("RSA"); /* * using the KeyFactory object to generate a PublicKey from the key * specification. */ publickKey = keyFactory.generatePublic(pubKeySpec); byte[] signHash = Base64.decodeBase64(signedHash); byo = new ByteArrayOutputStream(); byo.write(signHash); byte[] signChar = byo.toByteArray(); ByteArrayInputStream byi = new ByteArrayInputStream(signChar); /* Next, input the signature bytes from the file specified */ byte[] sigToVerify = new byte[byi.available()]; byi.read(sigToVerify); byi.close(); /* Instantiating Signature */ Signature signature = Signature.getInstance(certs.getSigAlgName()); /* Initializing the Public Key in Signature */ signature.initVerify(publickKey); /* Supply the Signature Object With the Data to be Verified */ BufferedInputStream bufin = new BufferedInputStream(byi); byte[] buffer = new byte[1024]; int len; while (bufin.available() != 0) { len = bufin.read(buffer); signature.update(buffer, 0, len); }; bufin.close(); /* Verify the Signature */ isVerified = signature.verify(sigToVerify); } catch (Exception e) { System.err.println("Caught exception" + e.toString()); } return isVerified; } |
我得到的结果是错误的
1 | **Am i Missing something or is this piece of code correct ?** |
我非常感谢你的帮助。谢谢。
我复制了原始代码并将我的注释放入代码中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | // X509Certificate is class name, it cannot be variable name public static boolean verifySignedHash(String X509Certificate, String hash, String signedHash) { // Java is not C89 you don't have to declare variables in the beginning // of function, this reduces readability of the code and allows misuse boolean isVerified = false; ByteArrayInputStream inputStream = null; ByteArrayOutputStream outputStream = null; ByteArrayOutputStream byo = null; try { outputStream = new ByteArrayOutputStream(); byte[] data = Base64.decodeBase64(X509Certificate); /* writing decoded X509 certificate to the ByteArrayOutputStream */ outputStream.write(data); byte[] inp = outputStream.toByteArray(); // at this point inp is the same array as data, this makes no sence // and reduce performance inputStream = new ByteArrayInputStream(inp); /* Getting the certificate from the Input */ CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate certs = (X509Certificate) cf .generateCertificate(inputStream); /* import encoded public key */ // certs.getPublicKey() returns publicKey immediately, why to do // all these conversions? X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(certs .getPublicKey().getEncoded()); /* Instantiating KeyFactory for accesing the Keys as Object */ KeyFactory keyFactory = KeyFactory.getInstance("RSA"); /* * using the KeyFactory object to generate a PublicKey from the key * specification. */ publickKey = keyFactory.generatePublic(pubKeySpec); byte[] signHash = Base64.decodeBase64(signedHash); byo = new ByteArrayOutputStream(); byo.write(signHash); byte[] signChar = byo.toByteArray(); // Again, signChar is the same as signHash, why would you do that? ByteArrayInputStream byi = new ByteArrayInputStream(signChar); /* Next, input the signature bytes from the file specified */ byte[] sigToVerify = new byte[byi.available()]; byi.read(sigToVerify); byi.close(); // And now sigToVerify is the same as signChar and signHash. /* Instantiating Signature */ Signature signature = Signature.getInstance(certs.getSigAlgName()); /* Initializing the Public Key in Signature */ signature.initVerify(publickKey); /* Supply the Signature Object With the Data to be Verified */ // byi is already closed, you will get java.io.IOException: Stream closed BufferedInputStream bufin = new BufferedInputStream(byi); byte[] buffer = new byte[1024]; int len; while (bufin.available() != 0) { len = bufin.read(buffer); signature.update(buffer, 0, len); // Any way bufin contained signature, while you need feed // plaintext to signature.update() // I could assume unused parameter hash has something to do // with plaintext }; bufin.close(); /* Verify the Signature */ isVerified = signature.verify(sigToVerify); } catch (Exception e) { System.err.println("Caught exception" + e.toString()); } return isVerified; } |