List of usage examples for java.security MessageDigest reset
public void reset()
From source file:edu.mayo.informatics.lexgrid.convert.directConversions.UmlsCommon.UMLSBaseCode.java
/** * Adds qualification to concepts and associations in the LexGrid * repository.// w w w . ja va 2s . co m * * @param aq * Qualification information from the UMLS source. * @param constructHCD * Indicates whether artificial context values should be * constructed if not provided in the UMLS information. * @param rela * The relationship attribute defined by UMLS (can be empty or * null). * @param totalCount * The total number of context links qualified previously. * @return The number of contextual links qualified in the repository for * the given UMLS info. * @throws SQLException */ protected int loadContext(AssociationQualification aq, boolean constructHCD, String rela, int totalCount) throws SQLException { // If a context identifier was assigned, use it. // If a context identifier is not assigned and the option to construct // is enabled, // derive one based on the root concept code and path to root AUI // values. int contextLinks = 0; String hcd = aq.qualifierValue; if (constructHCD && StringUtils.isBlank(hcd) && StringUtils.isNotBlank(aq.pathToRoot) && StringUtils.isNotBlank(aq.sourceConceptCode)) { MessageDigest md = getSHA1(); md.reset(); md.update(aq.pathToRoot.getBytes()); hcd = String.valueOf(md.digest(aq.sourceConceptCode.getBytes())); } if (StringUtils.isBlank(hcd)) return 0; // Iterate through the path to root and determine the codes for // participating AUIs. We maintain a LRU cache of AUIs to codes to // assist. // If the associated code is not in the cache, find and cache it here. ListOrderedMap orderedPtrAUIToCode = new ListOrderedMap(); // Break up the path to root into AUIs ... String[] auis = aq.pathToRoot.split("\\."); if (auis.length > 0) { // Check the cache for each. If not found, perform and cache the // AUI to code mapping. PreparedStatement getPTRCode = umlsConnection2_ .prepareStatement("SELECT CODE FROM MRCONSO WHERE AUI = ?"); try { String nextCode, nextAUI; for (int i = 0; i < auis.length; i++) { // Check for registered code in the cache. nextAUI = auis[i]; nextCode = (String) auiToCodeCache_.get(nextAUI); // If not cached, perform lookup ... if (nextCode == null) { getPTRCode.setString(1, nextAUI); ResultSet ptrCodes = getPTRCode.executeQuery(); int count = 0; try { while (ptrCodes.next()) { count++; nextCode = ptrCodes.getString(1); } } finally { ptrCodes.close(); } // If one to one mapping (probably should always be, but // doesn't // hurt to check), add to the cache for quick lookup // later... if (count == 1) auiToCodeCache_.put(nextAUI, nextCode); } // Was it resolved? if (nextCode != null) orderedPtrAUIToCode.put(nextAUI, nextCode); } } finally { getPTRCode.close(); } } // Ensure we have included the original AUI to code mapping from the // provided UMLS qualification info; inserted last as the root // of the path. orderedPtrAUIToCode.put(aq.sourceConceptAUI, aq.sourceConceptCode); // ///////////////////////////////////////////////////////////////////// // We have all the participating codes and AUIs. // Add context qualifiers to the text presentation of each concept // based on code/AUI pairs. // ///////////////////////////////////////////////////////////////////// for (OrderedMapIterator omi = orderedPtrAUIToCode.orderedMapIterator(); omi.hasNext();) { omi.next(); String aui = (String) omi.getKey(); String code = (String) omi.getValue(); if (code != null) qualifyConceptPresentation(code, aui, aq.codingSchemeName, aq.qualifierName, hcd); } // ///////////////////////////////////////////////////////////////////// // At this point we have taken care of all the concept qualifiers. // Now find and similarly tag each participating association link // between AUIs in the path to root chain. // ///////////////////////////////////////////////////////////////////// // Statements to find LexGrid association to concept mappings. // Check source to target (parent association as processed) // or target to source (child association as processed). // Honor the association specified in the MRHIER entry, if provided. // For example, the UMLS 'inverse_isa' is mapped on load to 'hasSubtype' // association name; account for that here. String assoc = mapRela(rela); // If a specific relation attribute (rela) was not provided, consider // all relevant // hierarchical associations (including UMLS standard or source-specific // names). String assocParam = StringUtils.isNotBlank(assoc) ? '\'' + assoc + '\'' : toCommaDelimitedWithQuotes(getHierAssocNames(aq.codingSchemeName)); // Create statements to navigate both directions (up & down the // contextual chain). PreparedStatement getRelationship_1 = sqlConnection_.prepareStatement(new StringBuffer( "SELECT " + SQLTableConstants.TBLCOL_MULTIATTRIBUTESKEY + ", " + stc_.targetEntityCodeOrId + ", " + stc_.entityCodeOrAssociationId + ", " + stc_.sourceEntityCodeOrId + " FROM ") .append(stc_.getTableName(SQLTableConstants.ENTITY_ASSOCIATION_TO_ENTITY)) .append(" WHERE " + stc_.sourceEntityCodeOrId + " = ? AND " + stc_.targetEntityCodeOrId + " = ? AND") .append(" " + stc_.codingSchemeNameOrId + " = ? AND " + stc_.entityCodeOrAssociationId + " IN (") .append(assocParam).append(")").toString()); PreparedStatement getRelationship_2 = sqlConnection_.prepareStatement(new StringBuffer( "SELECT " + SQLTableConstants.TBLCOL_MULTIATTRIBUTESKEY + ", " + stc_.targetEntityCodeOrId + ", " + stc_.entityCodeOrAssociationId + ", " + stc_.sourceEntityCodeOrId + " FROM ") .append(stc_.getTableName(SQLTableConstants.ENTITY_ASSOCIATION_TO_ENTITY)) .append(" WHERE " + stc_.targetEntityCodeOrId + " = ? AND " + stc_.sourceEntityCodeOrId + " = ? AND") .append(" " + stc_.codingSchemeNameOrId + " = ? AND " + stc_.entityCodeOrAssociationId + " IN (") .append(assocParam).append(")").toString()); // Statement to update a multi-attributes key for an association // mapping. PreparedStatement updateMAK = sqlConnection_.prepareStatement(new StringBuffer("UPDATE ") .append(stc_.getTableName(SQLTableConstants.ENTITY_ASSOCIATION_TO_ENTITY)) .append(" SET " + SQLTableConstants.TBLCOL_MULTIATTRIBUTESKEY + " = ? " + " WHERE " + stc_.codingSchemeNameOrId + " = ?") .append(" AND " + stc_.sourceEntityCodeOrId + " = ? AND " + stc_.targetEntityCodeOrId + " = ?") .append(" AND " + stc_.entityCodeOrAssociationId + " = ?").toString()); // Locate and qualify each affected association link with the context ID // ... try { PreparedStatement[] stmts = new PreparedStatement[] { getRelationship_1, getRelationship_2 }; for (int s = 0; s < stmts.length; s++) { PreparedStatement stmt = stmts[s]; for (int i = orderedPtrAUIToCode.size() - 1; i > 0; i--) { String code = (String) orderedPtrAUIToCode.getValue(i); String codePrev = (String) orderedPtrAUIToCode.getValue(i - 1); stmt.setString(1, code); stmt.setString(2, codePrev); stmt.setString(3, aq.codingSchemeName); ResultSet results = stmt.executeQuery(); try { // Iterate through all relevant association links ... while (results.next()) { String multiAttributesKey = results .getString(SQLTableConstants.TBLCOL_MULTIATTRIBUTESKEY); String targetConceptCode = results.getString(stc_.targetEntityCodeOrId); String sourceConceptCode = results.getString(stc_.sourceEntityCodeOrId); String association = results.getString(stc_.entityCodeOrAssociationId); // If there is no key to correlate to the // multi-attributes table, // construct and add now. if (multiAttributesKey == null) { StringBuffer key = new StringBuffer().append(System.currentTimeMillis()) .append((int) Math.floor((Math.random() * 100000))).append(totalCount); multiAttributesKey = key.substring(0, Math.min(50, key.length())); updateMAK.setString(1, multiAttributesKey); updateMAK.setString(2, aq.codingSchemeName); updateMAK.setString(3, sourceConceptCode); updateMAK.setString(4, targetConceptCode); updateMAK.setString(5, association); updateMAK.execute(); } // Add a context qualifier to the multi-attributes // table. try { addEntityAssociationQualifierToEntityAssociation(aq.codingSchemeName, multiAttributesKey, aq.qualifierName, hcd); contextLinks++; } catch (SQLException e) { // Because we qualify all relationships along // the PTR and // the HCD is identical for siblings at the same // PTR some // exceptions with regards to identical keys // will come up. // We try to bypass altogether if the message // indicates duplication. // However, message text can vary based on the // database engine. // Rather than exit in error, log the message // and continue. if (!e.getMessage().contains("Duplicate")) { messages_.warn("Unable to add context qualifier to association.", e); } } } } finally { results.close(); } } } } finally { updateMAK.close(); getRelationship_1.close(); getRelationship_2.close(); } return contextLinks; }
From source file:com.cloud.network.NetworkModelImpl.java
@Override public List<String[]> generateVmData(String userData, String serviceOffering, String zoneName, String vmName, long vmId, String publicKey, String password, Boolean isWindows) { final List<String[]> vmData = new ArrayList<String[]>(); if (userData != null) { vmData.add(new String[] { "userdata", "user-data", new String(Base64.decodeBase64(userData), StringUtils.getPreferredCharset()) }); }//from w w w.java 2s . c o m vmData.add(new String[] { "metadata", "service-offering", StringUtils.unicodeEscape(serviceOffering) }); vmData.add(new String[] { "metadata", "availability-zone", StringUtils.unicodeEscape(zoneName) }); vmData.add(new String[] { "metadata", "local-hostname", StringUtils.unicodeEscape(vmName) }); vmData.add(new String[] { "metadata", "instance-id", vmName }); vmData.add(new String[] { "metadata", "vm-id", String.valueOf(vmId) }); vmData.add(new String[] { "metadata", "public-keys", publicKey }); String cloudIdentifier = _configDao.getValue("cloud.identifier"); if (cloudIdentifier == null) { cloudIdentifier = ""; } else { cloudIdentifier = "CloudStack-{" + cloudIdentifier + "}"; } vmData.add(new String[] { "metadata", "cloud-identifier", cloudIdentifier }); if (password != null && !password.isEmpty() && !password.equals("saved_password")) { // Here we are calculating MD5 checksum to reduce the over head of calculating MD5 checksum // in windows VM in password reset script. if (isWindows) { MessageDigest md5 = null; try { md5 = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { s_logger.error("Unexpected exception " + e.getMessage(), e); throw new CloudRuntimeException("Unable to get MD5 MessageDigest", e); } md5.reset(); md5.update(password.getBytes(StringUtils.getPreferredCharset())); byte[] digest = md5.digest(); BigInteger bigInt = new BigInteger(1, digest); String hashtext = bigInt.toString(16); vmData.add(new String[] { "password", "vm-password-md5checksum", hashtext }); } vmData.add(new String[] { "password", "vm-password", password }); } return vmData; }
From source file:Hash.Hash.java
public static String getHash(File file) throws FileNotFoundException, IOException { MessageDigest md5Digest = null; try {//from w ww. j a va 2 s .c o m md5Digest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException ex) { return EMPTYHASH; } byte[] digestDef = md5Digest.digest(); byte[] digest = null; String ext = FilenameUtils.getExtension(file.getName().toLowerCase()); if (ext.equals("arw") || ext.equals("nef") || ext.equals("dng") || ext.equals("tif") || ext.equals("tiff")) { // <editor-fold defaultstate="collapsed" desc="raw"> try (BufferedInputStream rawIn = new BufferedInputStream(new FileInputStream(file.toString()));) { digest = startOfScanTiff(file, rawIn); } catch (IOException e) { errorOut("Hash", e); } // </editor-fold> } else { try (FileInputStream fileInStream = new FileInputStream(file.toString()); BufferedInputStream fileStream = new BufferedInputStream(fileInStream); DigestInputStream in = new DigestInputStream(fileStream, md5Digest);) { byte[] buffer = new byte[4096]; long length; switch (ext) { // <editor-fold defaultstate="collapsed" desc="mp4"> case "mp4": in.on(false); boolean EOF = false; do { length = readEndianValue(in, 4, false) - 8; // byte boxLength[] = readBytes(in, 4); String desc = new String(readBytes(in, 4)); // ByteBuffer wrapped = ByteBuffer.wrap(boxLength); // big-endian by default // length = wrapped.getInt() - 8; if (length == -7) { //largesize length = readEndianValue(in, 8, false) - 16; } else if (length == -8) { // until eof EOF = true; } else if (length == in.available()) { EOF = true; } if (desc.equals("mdat")) { in.on(true); while (buffer.length <= length) { int read = in.read(buffer); length -= read; } while (length > 0) { int read = in.read(buffer, 0, (int) length); if (read == -1) { digest = null; break; } length -= read; } // break; } else { if (!skipBytes(in, length)) break; } } while (!EOF); digest = md5Digest.digest(); break; // </editor-fold> // <editor-fold defaultstate="collapsed" desc="JPG"> case "jpg": case "jpeg": int scanLength; int scanLengthOld = 0; do { in.on(false); md5Digest.reset(); scanLength = 0; if (startOfScanJPG(fileStream) == -1) break; in.on(true); int c = 0; int oldc; do { oldc = c; c = in.read(); if (c == -1) { return EMPTYHASH; } scanLength++; } while (!(oldc == 0xFF && c == 0xD9/*217*/)); if (scanLength > scanLengthOld) { digest = md5Digest.digest(); scanLengthOld = scanLength; } } while (scanLengthOld < in.available()); break; // </editor-fold> default: in.on(true); while (in.read(buffer) != -1) { } digest = md5Digest.digest(); break; } } catch (IOException e) { errorOut("Hash", e); } } if (digest == null) { return EMPTYHASH; } if (Arrays.equals(digest, digestDef)) { return EMPTYHASH; } StringBuilder sb = new StringBuilder(); for (int i = 0; i < digest.length; ++i) { sb.append(Integer.toHexString((digest[i] & 0xFF) | 0x100).substring(1, 3)); } return sb.toString(); }
From source file:org.zywx.wbpalmstar.engine.universalex.EUExWindow.java
public void openAdMsg(String[] parm) { EBrowserWindow curWind = mBrwView.getBrowserWindow(); if (null == curWind) { return;//from ww w . jav a 2s. co m } WWidgetData wd = mBrwView.getCurrentWidget(); boolean b1 = mBrwView.checkType(EBrwViewEntry.VIEW_TYPE_MAIN); boolean b2 = 0 == wd.m_widgetAdStatus; boolean b3 = parm.length < 4; if (!b1 || b2 || b3) { // 0 means do not show ad return; } String inType = parm[0]; String inDTime = parm[1]; String inInterval = parm[2]; String inFlag = parm[3]; int type = 0, flag = 0, dtime = 0, interval = 0, w = RelativeLayout.LayoutParams.FILL_PARENT, h = 50; MessageDigest md = null; int density = ESystemInfo.getIntence().mDensityDpi; switch (density) { case DisplayMetrics.DENSITY_LOW: h = 40; break; case DisplayMetrics.DENSITY_MEDIUM: h = 50; break; case DisplayMetrics.DENSITY_HIGH: h = 60; break; case 320: // DisplayMetrics.DENSITY_XHIGH from 2.3.3 h = 70; break; } try { if (null != inType && inType.length() != 0) { type = Integer.parseInt(inType); } if (null != inDTime && inDTime.length() != 0) { dtime = Integer.parseInt(inDTime); } if (null != inInterval && inInterval.length() != 0) { interval = Integer.parseInt(inInterval); } if (null != inFlag && inFlag.length() != 0) { flag = Integer.parseInt(inFlag); } md = MessageDigest.getInstance("MD5"); } catch (Exception e) { errorCallback(0, EUExCallback.F_E_UEXWINDOW_EVAL, "Illegal parameter"); return; } StringBuffer sb = new StringBuffer(m_AdUrl); sb.append("?appid="); sb.append(wd.m_appId); sb.append("&pt=1"); sb.append("&dw="); sb.append(ESystemInfo.getIntence().mWidthPixels); sb.append("&dh="); sb.append(ESystemInfo.getIntence().mHeightPixels); sb.append("&md5="); if (null == md) { return; } String jid = wd.m_appId + "BD7463CD-D608-BEB4-C633-EF3574213060"; md.reset(); md.update(jid.getBytes()); byte[] md5Bytes = md.digest(); StringBuffer hexValue = new StringBuffer(); for (int i = 0; i < md5Bytes.length; i++) { int val = ((int) md5Bytes[i]) & 0xff; if (val < 16) hexValue.append("0"); hexValue.append(Integer.toHexString(val)); } sb.append(hexValue); sb.append("&type="); if (type == 1) { sb.append(1); h = w; } else { sb.append(0); } String url = sb.toString(); curWind.openAd(type, url, dtime * 1000, h, w, interval * 1000, flag); }
From source file:org.opends.server.extensions.Sha2Crypt.java
/** * Generates a libc6 crypt() compatible "$5$" or "$6$" SHA2 based hash value. * <p>//w ww . j a v a 2 s .c om * This is a nearly line by line conversion of the original C function. The numbered comments are from the algorithm * description, the short C-style ones from the original C code and the ones with "Remark" from me. * <p> * See {@link Crypt#crypt(String, String)} for details. * * @param keyBytes * plaintext to hash * @param salt * real salt value without prefix or "rounds=" * @param saltPrefix * either $5$ or $6$ * @param blocksize * a value that differs between $5$ and $6$ * @param algorithm * {@link MessageDigest} algorithm identifier string * @return complete hash value including prefix and salt * @throws IllegalArgumentException * if the given salt is <code>null</code> or does not match the allowed pattern * @throws IllegalArgumentException * when a {@link NoSuchAlgorithmException} is caught * @see MessageDigestAlgorithms */ private static String sha2Crypt(final byte[] keyBytes, final String salt, final String saltPrefix, final int blocksize, final String algorithm) { final int keyLen = keyBytes.length; // Extracts effective salt and the number of rounds from the given salt. int rounds = ROUNDS_DEFAULT; boolean roundsCustom = false; if (salt == null) { throw new IllegalArgumentException("Salt must not be null"); } final Matcher m = SALT_PATTERN.matcher(salt); if (!m.find()) { throw new IllegalArgumentException("Invalid salt value: " + salt); } if (m.group(3) != null) { rounds = Integer.parseInt(m.group(3)); rounds = Math.max(ROUNDS_MIN, Math.min(ROUNDS_MAX, rounds)); roundsCustom = true; } final String saltString = m.group(4); final byte[] saltBytes = saltString.getBytes(StandardCharsets.UTF_8); final int saltLen = saltBytes.length; // 1. start digest A // Prepare for the real work. MessageDigest ctx = getDigest(algorithm); // 2. the password string is added to digest A /* * Add the key string. */ ctx.update(keyBytes); // 3. the salt string is added to digest A. This is just the salt string // itself without the enclosing '$', without the magic salt_prefix $5$ and // $6$ respectively and without the rounds=<N> specification. // // NB: the MD5 algorithm did add the $1$ salt_prefix. This is not deemed // necessary since it is a constant string and does not add security // and /possibly/ allows a plain text attack. Since the rounds=<N> // specification should never be added this would also create an // inconsistency. /* * The last part is the salt string. This must be at most 16 characters and it ends at the first `$' character * (for compatibility with existing implementations). */ ctx.update(saltBytes); // 4. start digest B /* * Compute alternate sha512 sum with input KEY, SALT, and KEY. The final result will be added to the first * context. */ MessageDigest altCtx = getDigest(algorithm); // 5. add the password to digest B /* * Add key. */ altCtx.update(keyBytes); // 6. add the salt string to digest B /* * Add salt. */ altCtx.update(saltBytes); // 7. add the password again to digest B /* * Add key again. */ altCtx.update(keyBytes); // 8. finish digest B /* * Now get result of this (32 bytes) and add it to the other context. */ byte[] altResult = altCtx.digest(); // 9. For each block of 32 or 64 bytes in the password string (excluding // the terminating NUL in the C representation), add digest B to digest A /* * Add for any character in the key one byte of the alternate sum. */ /* * (Remark: the C code comment seems wrong for key length > 32!) */ int cnt = keyBytes.length; while (cnt > blocksize) { ctx.update(altResult, 0, blocksize); cnt -= blocksize; } // 10. For the remaining N bytes of the password string add the first // N bytes of digest B to digest A ctx.update(altResult, 0, cnt); // 11. For each bit of the binary representation of the length of the // password string up to and including the highest 1-digit, starting // from to lowest bit position (numeric value 1): // // a) for a 1-digit add digest B to digest A // // b) for a 0-digit add the password string // // NB: this step differs significantly from the MD5 algorithm. It // adds more randomness. /* * Take the binary representation of the length of the key and for every 1 add the alternate sum, for every 0 * the key. */ cnt = keyBytes.length; while (cnt > 0) { if ((cnt & 1) != 0) { ctx.update(altResult, 0, blocksize); } else { ctx.update(keyBytes); } cnt >>= 1; } // 12. finish digest A /* * Create intermediate result. */ altResult = ctx.digest(); // 13. start digest DP /* * Start computation of P byte sequence. */ altCtx = getDigest(algorithm); // 14. for every byte in the password (excluding the terminating NUL byte // in the C representation of the string) // // add the password to digest DP /* * For every character in the password add the entire password. */ for (int i = 1; i <= keyLen; i++) { altCtx.update(keyBytes); } // 15. finish digest DP /* * Finish the digest. */ byte[] tempResult = altCtx.digest(); // 16. produce byte sequence P of the same length as the password where // // a) for each block of 32 or 64 bytes of length of the password string // the entire digest DP is used // // b) for the remaining N (up to 31 or 63) bytes use the first N // bytes of digest DP /* * Create byte sequence P. */ final byte[] pBytes = new byte[keyLen]; int cp = 0; while (cp < keyLen - blocksize) { System.arraycopy(tempResult, 0, pBytes, cp, blocksize); cp += blocksize; } System.arraycopy(tempResult, 0, pBytes, cp, keyLen - cp); // 17. start digest DS /* * Start computation of S byte sequence. */ altCtx = getDigest(algorithm); // 18. repeast the following 16+A[0] times, where A[0] represents the first // byte in digest A interpreted as an 8-bit unsigned value // // add the salt to digest DS /* * For every character in the password add the entire password. */ for (int i = 1; i <= 16 + (altResult[0] & 0xff); i++) { altCtx.update(saltBytes); } // 19. finish digest DS /* * Finish the digest. */ tempResult = altCtx.digest(); // 20. produce byte sequence S of the same length as the salt string where // // a) for each block of 32 or 64 bytes of length of the salt string // the entire digest DS is used // // b) for the remaining N (up to 31 or 63) bytes use the first N // bytes of digest DS /* * Create byte sequence S. */ // Remark: The salt is limited to 16 chars, how does this make sense? final byte[] sBytes = new byte[saltLen]; cp = 0; while (cp < saltLen - blocksize) { System.arraycopy(tempResult, 0, sBytes, cp, blocksize); cp += blocksize; } System.arraycopy(tempResult, 0, sBytes, cp, saltLen - cp); // 21. repeat a loop according to the number specified in the rounds=<N> // specification in the salt (or the default value if none is // present). Each round is numbered, starting with 0 and up to N-1. // // The loop uses a digest as input. In the first round it is the // digest produced in step 12. In the latter steps it is the digest // produced in step 21.h. The following text uses the notation // "digest A/C" to describe this behavior. /* * Repeatedly run the collected hash value through sha512 to burn CPU cycles. */ for (int i = 0; i <= rounds - 1; i++) { // a) start digest C /* * New context. */ ctx = getDigest(algorithm); // b) for odd round numbers add the byte sequence P to digest C // c) for even round numbers add digest A/C /* * Add key or last result. */ if ((i & 1) != 0) { ctx.update(pBytes, 0, keyLen); } else { ctx.update(altResult, 0, blocksize); } // d) for all round numbers not divisible by 3 add the byte sequence S /* * Add salt for numbers not divisible by 3. */ if (i % 3 != 0) { ctx.update(sBytes, 0, saltLen); } // e) for all round numbers not divisible by 7 add the byte sequence P /* * Add key for numbers not divisible by 7. */ if (i % 7 != 0) { ctx.update(pBytes, 0, keyLen); } // f) for odd round numbers add digest A/C // g) for even round numbers add the byte sequence P /* * Add key or last result. */ if ((i & 1) != 0) { ctx.update(altResult, 0, blocksize); } else { ctx.update(pBytes, 0, keyLen); } // h) finish digest C. /* * Create intermediate result. */ altResult = ctx.digest(); } // 22. Produce the output string. This is an ASCII string of the maximum // size specified above, consisting of multiple pieces: // // a) the salt salt_prefix, $5$ or $6$ respectively // // b) the rounds=<N> specification, if one was present in the input // salt string. A trailing '$' is added in this case to separate // the rounds specification from the following text. // // c) the salt string truncated to 16 characters // // d) a '$' character /* * Now we can construct the result string. It consists of three parts. */ final StringBuilder buffer = new StringBuilder(saltPrefix); if (roundsCustom) { buffer.append(ROUNDS_PREFIX); buffer.append(rounds); buffer.append("$"); } buffer.append(saltString); buffer.append("$"); // e) the base-64 encoded final C digest. The encoding used is as // follows: // [...] // // Each group of three bytes from the digest produces four // characters as output: // // 1. character: the six low bits of the first byte // 2. character: the two high bits of the first byte and the // four low bytes from the second byte // 3. character: the four high bytes from the second byte and // the two low bits from the third byte // 4. character: the six high bits from the third byte // // The groups of three bytes are as follows (in this sequence). // These are the indices into the byte array containing the // digest, starting with index 0. For the last group there are // not enough bytes left in the digest and the value zero is used // in its place. This group also produces only three or two // characters as output for SHA-512 and SHA-512 respectively. // This was just a safeguard in the C implementation: // int buflen = salt_prefix.length() - 1 + ROUNDS_PREFIX.length() + 9 + 1 + salt_string.length() + 1 + 86 + 1; if (blocksize == 32) { B64.b64from24bit(altResult[0], altResult[10], altResult[20], 4, buffer); B64.b64from24bit(altResult[21], altResult[1], altResult[11], 4, buffer); B64.b64from24bit(altResult[12], altResult[22], altResult[2], 4, buffer); B64.b64from24bit(altResult[3], altResult[13], altResult[23], 4, buffer); B64.b64from24bit(altResult[24], altResult[4], altResult[14], 4, buffer); B64.b64from24bit(altResult[15], altResult[25], altResult[5], 4, buffer); B64.b64from24bit(altResult[6], altResult[16], altResult[26], 4, buffer); B64.b64from24bit(altResult[27], altResult[7], altResult[17], 4, buffer); B64.b64from24bit(altResult[18], altResult[28], altResult[8], 4, buffer); B64.b64from24bit(altResult[9], altResult[19], altResult[29], 4, buffer); B64.b64from24bit((byte) 0, altResult[31], altResult[30], 3, buffer); } else { B64.b64from24bit(altResult[0], altResult[21], altResult[42], 4, buffer); B64.b64from24bit(altResult[22], altResult[43], altResult[1], 4, buffer); B64.b64from24bit(altResult[44], altResult[2], altResult[23], 4, buffer); B64.b64from24bit(altResult[3], altResult[24], altResult[45], 4, buffer); B64.b64from24bit(altResult[25], altResult[46], altResult[4], 4, buffer); B64.b64from24bit(altResult[47], altResult[5], altResult[26], 4, buffer); B64.b64from24bit(altResult[6], altResult[27], altResult[48], 4, buffer); B64.b64from24bit(altResult[28], altResult[49], altResult[7], 4, buffer); B64.b64from24bit(altResult[50], altResult[8], altResult[29], 4, buffer); B64.b64from24bit(altResult[9], altResult[30], altResult[51], 4, buffer); B64.b64from24bit(altResult[31], altResult[52], altResult[10], 4, buffer); B64.b64from24bit(altResult[53], altResult[11], altResult[32], 4, buffer); B64.b64from24bit(altResult[12], altResult[33], altResult[54], 4, buffer); B64.b64from24bit(altResult[34], altResult[55], altResult[13], 4, buffer); B64.b64from24bit(altResult[56], altResult[14], altResult[35], 4, buffer); B64.b64from24bit(altResult[15], altResult[36], altResult[57], 4, buffer); B64.b64from24bit(altResult[37], altResult[58], altResult[16], 4, buffer); B64.b64from24bit(altResult[59], altResult[17], altResult[38], 4, buffer); B64.b64from24bit(altResult[18], altResult[39], altResult[60], 4, buffer); B64.b64from24bit(altResult[40], altResult[61], altResult[19], 4, buffer); B64.b64from24bit(altResult[62], altResult[20], altResult[41], 4, buffer); B64.b64from24bit((byte) 0, (byte) 0, altResult[63], 2, buffer); } /* * Clear the buffer for the intermediate result so that people attaching to processes or reading core dumps * cannot get any information. */ // Is there a better way to do this with the JVM? Arrays.fill(tempResult, (byte) 0); Arrays.fill(pBytes, (byte) 0); Arrays.fill(sBytes, (byte) 0); ctx.reset(); altCtx.reset(); Arrays.fill(keyBytes, (byte) 0); Arrays.fill(saltBytes, (byte) 0); return buffer.toString(); }