public synchronized String generateSignature(byte[] message) throws Exception { // Log.trace("Signed message length is " + message.length); try { digest.reset(); cipher.init(true, privateRsaKey); digest.update(message, 0, message.length); byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); DigestInfo info = new DigestInfo(new AlgorithmIdentifier(md5, null), hash); byte[] bytes = info.getEncoded(ASN1Encoding.DER); byte[] signature = cipher.processBlock(bytes, 0, bytes.length); return new String(org.bouncycastle.util.encoders.Base64.encode(signature)); } catch (Exception e) { throw new Exception("Ошибка создания подписи:\n" + e.getMessage()); } }
private DigestInfo derDecode(byte[] encoding) throws IOException, CMSException { if (encoding[0] != (DERTags.CONSTRUCTED | DERTags.SEQUENCE)) { throw new IOException("not a digest info object"); } ASN1InputStream aIn = new ASN1InputStream(encoding); DigestInfo digInfo = new DigestInfo((ASN1Sequence) aIn.readObject()); // length check to avoid Bleichenbacher vulnerability if (digInfo.getEncoded().length != encoding.length) { throw new CMSException("malformed RSA signature"); } return digInfo; }
public synchronized void verifySignature(byte[] message, byte[] signature) throws Exception { try { digest.reset(); cipher.init(false, publicRsaKey); digest.update(message, 0, message.length); byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); DigestInfo info = new DigestInfo(new AlgorithmIdentifier(md5, null), hash); byte[] bytes = info.getEncoded(ASN1Encoding.DER); byte[] signatureData = org.bouncycastle.util.encoders.Base64.decode(signature); byte[] result = cipher.processBlock(signatureData, 0, signatureData.length); if ((result == null) || (result.length < hash.length)) { throw new Exception("Invalid signature (1)!"); } if (!compareFromTheEnd(hash, result)) { throw new Exception("Invalid signature (2)!"); } } catch (Exception e) { throw new Exception("Error checking signature:\n" + e.getMessage()); } }