/** generate a signature for the loaded message using the key we were initialised with. */ public byte[] generateSignature() throws CryptoException { int digSize = digest.getDigestSize(); int t = 0; int delta = 0; if (trailer == TRAILER_IMPLICIT) { t = 8; delta = block.length - digSize - 1; digest.doFinal(block, delta); block[block.length - 1] = (byte) TRAILER_IMPLICIT; } else { t = 16; delta = block.length - digSize - 2; digest.doFinal(block, delta); block[block.length - 2] = (byte) (trailer >>> 8); block[block.length - 1] = (byte) trailer; } byte header = 0; int x = (digSize + messageLength) * 8 + t + 4 - keyBits; if (x > 0) { int mR = messageLength - ((x + 7) / 8); header = 0x60; delta -= mR; System.arraycopy(mBuf, 0, block, delta, mR); } else { header = 0x40; delta -= messageLength; System.arraycopy(mBuf, 0, block, delta, messageLength); } if ((delta - 1) > 0) { for (int i = delta - 1; i != 0; i--) { block[i] = (byte) 0xbb; } block[delta - 1] ^= (byte) 0x01; block[0] = (byte) 0x0b; block[0] |= header; } else { block[0] = (byte) 0x0a; block[0] |= header; } byte[] b = cipher.processBlock(block, 0, block.length); clearBlock(mBuf); clearBlock(block); return b; }
/** the derived key function, the ith hash of the password and the salt. */ private byte[] generateDerivedKey() { byte[] digestBytes = new byte[digest.getDigestSize()]; digest.update(password, 0, password.length); digest.update(salt, 0, salt.length); digest.doFinal(digestBytes, 0); for (int i = 1; i < iterationCount; i++) { digest.update(digestBytes, 0, digestBytes.length); digest.doFinal(digestBytes, 0); } return digestBytes; }
public static byte[] hashContents(byte[] contents) { final Digest digest = new SHA256Digest(); digest.update(contents, 0, contents.length); final byte[] digestValue = new byte[digest.getDigestSize()]; digest.doFinal(digestValue, 0); return digestValue; }
protected byte[] engineSign() throws SignatureException { byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); try { byte[] sigBytes = new byte[64]; BigInteger[] sig = signer.generateSignature(hash); byte[] r = sig[0].toByteArray(); byte[] s = sig[1].toByteArray(); if (s[0] != 0) { System.arraycopy(s, 0, sigBytes, 32 - s.length, s.length); } else { System.arraycopy(s, 1, sigBytes, 32 - (s.length - 1), s.length - 1); } if (r[0] != 0) { System.arraycopy(r, 0, sigBytes, 64 - r.length, r.length); } else { System.arraycopy(r, 1, sigBytes, 64 - (r.length - 1), r.length - 1); } return sigBytes; } catch (Exception e) { throw new SignatureException(e.toString()); } }
private void appendHash(BitString m, byte[] hash) { hashAlg.update(seed, 0, seed.length); putInt(hashAlg, counter); hashAlg.doFinal(hash, 0); m.appendBits(hash); }
/** * fill len bytes of the output buffer with bytes generated from the derivation function. * * @throws IllegalArgumentException if the size of the request will cause an overflow. * @throws DataLengthException if the out buffer is too small. */ public int generateBytes(byte[] out, int outOff, int len) throws DataLengthException, IllegalArgumentException { if ((out.length - len) < outOff) { throw new DataLengthException("output buffer too small"); } long oBytes = len; int outLen = digest.getDigestSize(); // // this is at odds with the standard implementation, the // maximum value should be hBits * (2^32 - 1) where hBits // is the digest output size in bits. We can't have an // array with a long index at the moment... // if (oBytes > ((2L << 32) - 1)) { throw new IllegalArgumentException("Output length too large"); } int cThreshold = (int) ((oBytes + outLen - 1) / outLen); byte[] dig = new byte[digest.getDigestSize()]; byte[] C = new byte[4]; Pack.intToBigEndian(counterStart, C, 0); int counterBase = counterStart & ~0xFF; for (int i = 0; i < cThreshold; i++) { digest.update(shared, 0, shared.length); digest.update(C, 0, C.length); if (iv != null) { digest.update(iv, 0, iv.length); } digest.doFinal(dig, 0); if (len > outLen) { System.arraycopy(dig, 0, out, outOff, outLen); outOff += outLen; len -= outLen; } else { System.arraycopy(dig, 0, out, outOff, len); } if (++C[3] == 0) { counterBase += 0x100; Pack.intToBigEndian(counterBase, C, 0); } } digest.reset(); return (int) oBytes; }
/** * Some key wrap algorithms make use of the Key Checksum defined in CMS [CMS-Algorithms]. This is * used to provide an integrity check value for the key being wrapped. The algorithm is * * <p>- Compute the 20 octet SHA-1 hash on the key being wrapped. - Use the first 8 octets of this * hash as the checksum value. * * @param key * @return the CMS checksum. * @throws RuntimeException * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum */ private byte[] calculateCMSKeyChecksum(byte[] key) { byte[] result = new byte[8]; sha1.update(key, 0, key.length); sha1.doFinal(digest, 0); System.arraycopy(digest, 0, result, 0, 8); return result; }
/** * Computes the digest for the given data in a single operation. * * @param input Data to be digested. * @return Message digest as byte array. */ public byte[] digest(final byte[] input) { if (salt != null) { digest.update(salt, 0, salt.length); } digest.update(input, 0, input.length); final byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); return hash; }
private void testDetachedRSA() throws Exception { Digest md = new SHA1Digest(); List certList = new ArrayList(); CMSTypedData msg = new CMSProcessableByteArray("Hello world!".getBytes()); certList.add(_origCert); certList.add(_signCert); Store certs = new CollectionStore(certList); CMSSignedDataGenerator gen = new CMSSignedDataGenerator(); byte[] digValue = new byte[md.getDigestSize()]; byte[] data = "Hello world!".getBytes(); md.update(data, 0, data.length); md.doFinal(digValue, 0); Attribute attr = new Attribute(CMSAttributes.messageDigest, new DERSet(new DEROctetString(digValue))); ASN1EncodableVector v = new ASN1EncodableVector(); v.add(attr); AsymmetricKeyParameter privKey = (AsymmetricKeyParameter) _origKP.getPrivate(); AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1withRSA"); AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId); BcContentSignerBuilder contentSignerBuilder = new BcRSAContentSignerBuilder(sigAlgId, digAlgId); gen.addSignerInfoGenerator( new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider()) .setSignedAttributeGenerator( new DefaultSignedAttributeTableGenerator(new AttributeTable(v))) .build(contentSignerBuilder.build(privKey), _origCert)); gen.addCertificates(certs); CMSSignedData s = gen.generate(new CMSAbsentContent(), false); // // the signature is detached, so need to add msg before passing on // s = new CMSSignedData(msg, s.getEncoded()); // // compute expected content digest // verifyRSASignatures(s, digValue); }
public boolean isPublicKeyBlackListed(PublicKey publicKey) { byte[] encoded = publicKey.getEncoded(); Digest digest = AndroidDigestFactory.getSHA1(); digest.update(encoded, 0, encoded.length); byte[] out = new byte[digest.getDigestSize()]; digest.doFinal(out, 0); for (byte[] blacklisted : pubkeyBlacklist) { if (Arrays.equals(blacklisted, Hex.encode(out))) { return true; } } return false; }
/** * Calculates the MacKey (i.e. the key to use when calculating the MagTag for key confirmation). * * <p> * * <p> * * <pre> * MacKey = H(K || "JPAKE_KC") * </pre> */ private static byte[] calculateMacKey(BigInteger keyingMaterial, Digest digest) { digest.reset(); updateDigest(digest, keyingMaterial); /* * This constant is used to ensure that the macKey is NOT the same as the derived key. */ updateDigest(digest, "JPAKE_KC"); byte[] output = new byte[digest.getDigestSize()]; digest.doFinal(output, 0); return output; }
private static BigInteger calculateHashForZeroKnowledgeProof( BigInteger g, BigInteger gr, BigInteger gx, String participantId, Digest digest) { digest.reset(); updateDigestIncludingSize(digest, g); updateDigestIncludingSize(digest, gr); updateDigestIncludingSize(digest, gx); updateDigestIncludingSize(digest, participantId); byte[] output = new byte[digest.getDigestSize()]; digest.doFinal(output, 0); return new BigInteger(output); }
/** * Computes the digest for all the data in the stream by reading data and hashing it in chunks. * * @param in Input stream containing data to be digested. * @return Message digest as byte array. * @throws IOException On input stream read errors. */ public byte[] digest(final InputStream in) throws IOException { if (in == null) { throw new IllegalArgumentException("Input stream cannot be null."); } final byte[] buffer = new byte[CHUNK_SIZE]; int count; if (salt != null) { digest.update(salt, 0, salt.length); } while ((count = in.read(buffer, 0, CHUNK_SIZE)) > 0) { digest.update(buffer, 0, count); } final byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); return hash; }
public byte[] calculateFingerprint(PublicKeyPacket publicPk) throws PGPException { BCPGKey key = publicPk.getKey(); Digest digest; if (publicPk.getVersion() <= 3) { RSAPublicBCPGKey rK = (RSAPublicBCPGKey) key; try { digest = new MD5Digest(); byte[] bytes = new MPInteger(rK.getModulus()).getEncoded(); digest.update(bytes, 2, bytes.length - 2); bytes = new MPInteger(rK.getPublicExponent()).getEncoded(); digest.update(bytes, 2, bytes.length - 2); } catch (IOException e) { throw new PGPException("can't encode key components: " + e.getMessage(), e); } } else { try { byte[] kBytes = publicPk.getEncodedContents(); digest = new SHA1Digest(); digest.update((byte) 0x99); digest.update((byte) (kBytes.length >> 8)); digest.update((byte) kBytes.length); digest.update(kBytes, 0, kBytes.length); } catch (IOException e) { throw new PGPException("can't encode key components: " + e.getMessage(), e); } } byte[] digBuf = new byte[digest.getDigestSize()]; digest.doFinal(digBuf, 0); return digBuf; }
protected boolean engineVerify(byte[] sigBytes) throws SignatureException { byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); BigInteger[] sig; try { byte[] r = new byte[32]; byte[] s = new byte[32]; System.arraycopy(sigBytes, 0, s, 0, 32); System.arraycopy(sigBytes, 32, r, 0, 32); sig = new BigInteger[2]; sig[0] = new BigInteger(1, r); sig[1] = new BigInteger(1, s); } catch (Exception e) { throw new SignatureException("error decoding signature bytes."); } return signer.verifySignature(hash, sig[0], sig[1]); }
/** * Computes the upcoming currentAuthpath of layer <code>layer</code> using the revisited * authentication path computation of Dahmen/Schneider 2008 * * @param layer the actual layer */ private void computeAuthPaths(int layer) { int Phi = index[layer]; int H = heightOfTrees[layer]; int K = this.K[layer]; // update all nextSeeds for seed scheduling for (int i = 0; i < H - K; i++) { currentTreehash[layer][i].updateNextSeed(gmssRandom); } // STEP 1 of Algorithm int Tau = heightOfPhi(Phi); byte[] OTSseed = new byte[mdLength]; OTSseed = gmssRandom.nextSeed(currentSeeds[layer]); // STEP 2 of Algorithm // if phi's parent on height tau + 1 if left node, store auth_tau // in keep_tau. // TODO check it, formerly was // int L = Phi / (int) Math.floor(Math.pow(2, Tau + 1)); // L %= 2; int L = (Phi >>> (Tau + 1)) & 1; byte[] tempKeep = new byte[mdLength]; // store the keep node not in keep[layer][tau/2] because it might be in // use // wait until the space is freed in step 4a if (Tau < H - 1 && L == 0) { System.arraycopy(currentAuthPaths[layer][Tau], 0, tempKeep, 0, mdLength); } byte[] help = new byte[mdLength]; // STEP 3 of Algorithm // if phi is left child, compute and store leaf for next currentAuthPath // path, // (obtained by veriying current signature) if (Tau == 0) { // LEAFCALC !!! if (layer == numLayer - 1) { // lowest layer computes the // necessary leaf completely at this // time WinternitzOTSignature ots = new WinternitzOTSignature(OTSseed, digestProvider.get(), otsIndex[layer]); help = ots.getPublicKey(); } else { // other layers use the precomputed leafs in // nextNextLeaf byte[] dummy = new byte[mdLength]; System.arraycopy(currentSeeds[layer], 0, dummy, 0, mdLength); gmssRandom.nextSeed(dummy); help = upperLeaf[layer].getLeaf(); this.upperLeaf[layer].initLeafCalc(dummy); // WinternitzOTSVerify otsver = new // WinternitzOTSVerify(algNames, otsIndex[layer]); // byte[] help2 = otsver.Verify(currentRoot[layer], // currentRootSig[layer]); // System.out.println(" --- " + layer + " " + // ByteUtils.toHexString(help) + " " + // ByteUtils.toHexString(help2)); } System.arraycopy(help, 0, currentAuthPaths[layer][0], 0, mdLength); } else { // STEP 4a of Algorithm // get new left currentAuthPath node on height tau byte[] toBeHashed = new byte[mdLength << 1]; System.arraycopy(currentAuthPaths[layer][Tau - 1], 0, toBeHashed, 0, mdLength); // free the shared keep[layer][tau/2] System.arraycopy( keep[layer][(int) Math.floor((Tau - 1) / 2)], 0, toBeHashed, mdLength, mdLength); messDigestTrees.update(toBeHashed, 0, toBeHashed.length); currentAuthPaths[layer][Tau] = new byte[messDigestTrees.getDigestSize()]; messDigestTrees.doFinal(currentAuthPaths[layer][Tau], 0); // STEP 4b and 4c of Algorithm // copy right nodes to currentAuthPath on height 0..Tau-1 for (int i = 0; i < Tau; i++) { // STEP 4b of Algorithm // 1st: copy from treehashs if (i < H - K) { if (currentTreehash[layer][i].wasFinished()) { System.arraycopy( currentTreehash[layer][i].getFirstNode(), 0, currentAuthPaths[layer][i], 0, mdLength); currentTreehash[layer][i].destroy(); } else { System.err.println( "Treehash (" + layer + "," + i + ") not finished when needed in AuthPathComputation"); } } // 2nd: copy precomputed values from Retain if (i < H - 1 && i >= H - K) { if (currentRetain[layer][i - (H - K)].size() > 0) { // pop element from retain System.arraycopy( currentRetain[layer][i - (H - K)].lastElement(), 0, currentAuthPaths[layer][i], 0, mdLength); currentRetain[layer][i - (H - K)].removeElementAt( currentRetain[layer][i - (H - K)].size() - 1); } } // STEP 4c of Algorithm // initialize new stack at heights 0..Tau-1 if (i < H - K) { // create stacks anew int startPoint = Phi + 3 * (1 << i); if (startPoint < numLeafs[layer]) { // if (layer < 2) { // System.out.println("initialized TH " + i + " on layer // " + layer); // } currentTreehash[layer][i].initialize(); } } } } // now keep space is free to use if (Tau < H - 1 && L == 0) { System.arraycopy(tempKeep, 0, keep[layer][(int) Math.floor(Tau / 2)], 0, mdLength); } // only update empty stack at height h if all other stacks have // tailnodes with height >h // finds active stack with lowest node height, choses lower index in // case of tie // on the lowest layer leafs must be computed at once, no precomputation // is possible. So all treehash updates are done at once here if (layer == numLayer - 1) { for (int tmp = 1; tmp <= (H - K) / 2; tmp++) { // index of the treehash instance that receives the next update int minTreehash = getMinTreehashIndex(layer); // if active treehash is found update with a leaf if (minTreehash >= 0) { try { byte[] seed = new byte[mdLength]; System.arraycopy( this.currentTreehash[layer][minTreehash].getSeedActive(), 0, seed, 0, mdLength); byte[] seed2 = gmssRandom.nextSeed(seed); WinternitzOTSignature ots = new WinternitzOTSignature(seed2, this.digestProvider.get(), this.otsIndex[layer]); byte[] leaf = ots.getPublicKey(); currentTreehash[layer][minTreehash].update(this.gmssRandom, leaf); } catch (Exception e) { System.out.println(e); } } } } else { // on higher layers the updates are done later this.minTreehash[layer] = getMinTreehashIndex(layer); } }
/** return true if the signature represents a ISO9796-2 signature for the passed in message. */ public boolean verifySignature(byte[] signature) { byte[] block = null; boolean updateWithRecoveredCalled; if (preSig == null) { updateWithRecoveredCalled = false; try { block = cipher.processBlock(signature, 0, signature.length); } catch (Exception e) { return false; } } else { if (!Arrays.areEqual(preSig, signature)) { throw new IllegalStateException("updateWithRecoveredMessage called on different signature"); } updateWithRecoveredCalled = true; block = preBlock; preSig = null; preBlock = null; } if (((block[0] & 0xC0) ^ 0x40) != 0) { return returnFalse(block); } if (((block[block.length - 1] & 0xF) ^ 0xC) != 0) { return returnFalse(block); } int delta = 0; if (((block[block.length - 1] & 0xFF) ^ 0xBC) == 0) { delta = 1; } else { int sigTrail = ((block[block.length - 2] & 0xFF) << 8) | (block[block.length - 1] & 0xFF); Integer trailerObj = (Integer) trailerMap.get(digest.getAlgorithmName()); if (trailerObj != null) { if (sigTrail != trailerObj.intValue()) { throw new IllegalStateException( "signer initialised with wrong digest for trailer " + sigTrail); } } else { throw new IllegalArgumentException("unrecognised hash in signature"); } delta = 2; } // // find out how much padding we've got // int mStart = 0; for (mStart = 0; mStart != block.length; mStart++) { if (((block[mStart] & 0x0f) ^ 0x0a) == 0) { break; } } mStart++; // // check the hashes // byte[] hash = new byte[digest.getDigestSize()]; int off = block.length - delta - hash.length; // // there must be at least one byte of message string // if ((off - mStart) <= 0) { return returnFalse(block); } // // if we contain the whole message as well, check the hash of that. // if ((block[0] & 0x20) == 0) { fullMessage = true; // check right number of bytes passed in. if (messageLength > off - mStart) { return returnFalse(block); } digest.reset(); digest.update(block, mStart, off - mStart); digest.doFinal(hash, 0); boolean isOkay = true; for (int i = 0; i != hash.length; i++) { block[off + i] ^= hash[i]; if (block[off + i] != 0) { isOkay = false; } } if (!isOkay) { return returnFalse(block); } recoveredMessage = new byte[off - mStart]; System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length); } else { fullMessage = false; digest.doFinal(hash, 0); boolean isOkay = true; for (int i = 0; i != hash.length; i++) { block[off + i] ^= hash[i]; if (block[off + i] != 0) { isOkay = false; } } if (!isOkay) { return returnFalse(block); } recoveredMessage = new byte[off - mStart]; System.arraycopy(block, mStart, recoveredMessage, 0, recoveredMessage.length); } // // if they've input a message check what we've recovered against // what was input. // if (messageLength != 0 && !updateWithRecoveredCalled) { if (!isSameAs(mBuf, recoveredMessage)) { return returnFalse(block); } } clearBlock(mBuf); clearBlock(block); return true; }
/** * This function verifies the signature of the message that has been updated, with the aid of the * public key. * * @param message the message * @param signature the signature associated with the message * @return true if the signature has been verified, false otherwise. */ public boolean verifySignature(byte[] message, byte[] signature) { boolean success = false; // int halfSigLength = signature.length >>> 1; messDigestOTS.reset(); WinternitzOTSVerify otsVerify; int otsSigLength; byte[] help = message; byte[] otsSig; byte[] otsPublicKey; byte[][] authPath; byte[] dest; int nextEntry = 0; int index; // Verify signature // --- begin with message = 'message that was signed' // and then in each step message = subtree root for (int j = numLayer - 1; j >= 0; j--) { otsVerify = new WinternitzOTSVerify(digestProvider.get(), gmssPS.getWinternitzParameter()[j]); otsSigLength = otsVerify.getSignatureLength(); message = help; // get the subtree index index = gmssUtil.bytesToIntLittleEndian(signature, nextEntry); // 4 is the number of bytes in integer nextEntry += 4; // get one-time signature otsSig = new byte[otsSigLength]; System.arraycopy(signature, nextEntry, otsSig, 0, otsSigLength); nextEntry += otsSigLength; // compute public OTS key from the one-time signature otsPublicKey = otsVerify.Verify(message, otsSig); // test if OTSsignature is correct if (otsPublicKey == null) { System.err.println("OTS Public Key is null in GMSSSignature.verify"); return false; } // get authentication path from the signature authPath = new byte[gmssPS.getHeightOfTrees()[j]][mdLength]; for (int i = 0; i < authPath.length; i++) { System.arraycopy(signature, nextEntry, authPath[i], 0, mdLength); nextEntry = nextEntry + mdLength; } // compute the root of the subtree from the authentication path help = new byte[mdLength]; help = otsPublicKey; int count = 1 << authPath.length; count = count + index; for (int i = 0; i < authPath.length; i++) { dest = new byte[mdLength << 1]; if ((count % 2) == 0) { System.arraycopy(help, 0, dest, 0, mdLength); System.arraycopy(authPath[i], 0, dest, mdLength, mdLength); count = count / 2; } else { System.arraycopy(authPath[i], 0, dest, 0, mdLength); System.arraycopy(help, 0, dest, mdLength, help.length); count = (count - 1) / 2; } messDigestTrees.update(dest, 0, dest.length); help = new byte[messDigestTrees.getDigestSize()]; messDigestTrees.doFinal(help, 0); } } // now help contains the root of the maintree // test if help is equal to the GMSS public key if (Arrays.areEqual(pubKeyBytes, help)) { success = true; } return success; }
private void doHash(byte[] input, byte[] output) { _digest.update(input, 0, input.length); _digest.doFinal(output, 0); }
private static void hash(Digest d, byte[] input, byte[] output) { d.update(input, 0, input.length); d.doFinal(output, 0); }