org.apache.sshd.common.digest.DigestUtils Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.sshd.common.digest;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.Collection;
import java.util.Comparator;
import java.util.Objects;
import org.apache.sshd.common.Factory;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.NumberUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.buffer.BufferUtils;
import org.apache.sshd.common.util.security.SecurityUtils;
/**
* @author Apache MINA SSHD Project
*/
public final class DigestUtils {
private DigestUtils() {
throw new UnsupportedOperationException("No instance");
}
/**
* @param algorithm The digest algorithm - never {@code null}/empty
* @return {@code true} if this digest algorithm is supported
* @see SecurityUtils#getMessageDigest(String)
*/
public static boolean checkSupported(String algorithm) {
ValidateUtils.checkNotNullAndNotEmpty(algorithm, "No algorithm");
try {
MessageDigest digest = SecurityUtils.getMessageDigest(algorithm);
return digest != null; // just in case
} catch (Exception e) {
return false;
}
}
/**
* @param The generic type of digest factory
* @param algo The required algorithm name - ignored if {@code null}/empty
* @param comp The {@link Comparator} to use to compare algorithm names
* @param digests The factories to check - ignored if {@code null}/empty
* @return The first {@link DigestFactory} whose algorithm matches the required one according to the
* comparator - {@code null} if no match found
*/
public static D findDigestByAlgorithm(
String algo, Comparator super String> comp, Collection extends D> digests) {
if (GenericUtils.isEmpty(algo) || GenericUtils.isEmpty(digests)) {
return null;
}
for (D d : digests) {
if (comp.compare(algo, d.getAlgorithm()) == 0) {
return d;
}
}
return null;
}
/**
* @param The generic type of digest factory
* @param algo The required algorithm name - ignored if {@code null}/empty
* @param comp The {@link Comparator} to use to compare algorithm names
* @param factories The factories to check - ignored if {@code null}/empty
* @return The first {@link DigestFactory} whose algorithm matches the required one according to the
* comparator - {@code null} if no match found
*/
public static F findFactoryByAlgorithm(
String algo, Comparator super String> comp, Collection extends F> factories) {
if (GenericUtils.isEmpty(algo) || GenericUtils.isEmpty(factories)) {
return null;
}
for (F f : factories) {
if (comp.compare(algo, f.getAlgorithm()) == 0) {
return f;
}
}
return null;
}
/**
* @param f The {@link Factory} to create the {@link Digest} to use
* @param s The {@link String} to digest - ignored if {@code null}/empty, otherwise its UTF-8
* representation is used as input for the fingerprint
* @return The fingerprint - {@code null} if {@code null}/empty input
* @throws Exception If failed to calculate the digest
* @see #getFingerPrint(Digest, String, Charset)
*/
public static String getFingerPrint(Factory extends Digest> f, String s) throws Exception {
return getFingerPrint(f, s, StandardCharsets.UTF_8);
}
/**
* @param f The {@link Factory} to create the {@link Digest} to use
* @param s The {@link String} to digest - ignored if {@code null}/empty
* @param charset The {@link Charset} to use in order to convert the string to its byte representation to use as
* input for the fingerprint
* @return The fingerprint - {@code null} if {@code null}/empty input
* @throws Exception If failed to calculate the digest
*/
public static String getFingerPrint(Factory extends Digest> f, String s, Charset charset) throws Exception {
return getFingerPrint(Objects.requireNonNull(f, "No factory").create(), s, charset);
}
/**
* @param d The {@link Digest} to use
* @param s The {@link String} to digest - ignored if {@code null}/empty, otherwise its UTF-8
* representation is used as input for the fingerprint
* @return The fingerprint - {@code null} if {@code null}/empty input
* @throws Exception If failed to calculate the digest
* @see #getFingerPrint(Digest, String, Charset)
*/
public static String getFingerPrint(Digest d, String s) throws Exception {
return getFingerPrint(d, s, StandardCharsets.UTF_8);
}
/**
* @param d The {@link Digest} to use
* @param s The {@link String} to digest - ignored if {@code null}/empty
* @param charset The {@link Charset} to use in order to convert the string to its byte representation to use as
* input for the fingerprint
* @return The fingerprint - {@code null} if {@code null}/empty input
* @throws Exception If failed to calculate the digest
*/
public static String getFingerPrint(Digest d, String s, Charset charset) throws Exception {
if (GenericUtils.isEmpty(s)) {
return null;
} else {
return DigestUtils.getFingerPrint(d, s.getBytes(charset));
}
}
/**
* @param f The {@link Factory} to create the {@link Digest} to use
* @param buf The data buffer to be fingerprint-ed
* @return The fingerprint - {@code null} if empty data buffer
* @throws Exception If failed to calculate the fingerprint
* @see #getFingerPrint(Factory, byte[], int, int)
*/
public static String getFingerPrint(Factory extends Digest> f, byte... buf) throws Exception {
return getFingerPrint(f, buf, 0, NumberUtils.length(buf));
}
/**
* @param f The {@link Factory} to create the {@link Digest} to use
* @param buf The data buffer to be fingerprint-ed
* @param offset The offset of the data in the buffer
* @param len The length of data - ignored if non-positive
* @return The fingerprint - {@code null} if non-positive length
* @throws Exception If failed to calculate the fingerprint
*/
public static String getFingerPrint(Factory extends Digest> f, byte[] buf, int offset, int len) throws Exception {
return getFingerPrint(Objects.requireNonNull(f, "No factory").create(), buf, offset, len);
}
/**
* @param d The {@link Digest} to use
* @param buf The data buffer to be fingerprint-ed
* @return The fingerprint - {@code null} if empty data buffer
* @throws Exception If failed to calculate the fingerprint
* @see #getFingerPrint(Digest, byte[], int, int)
*/
public static String getFingerPrint(Digest d, byte... buf) throws Exception {
return getFingerPrint(d, buf, 0, NumberUtils.length(buf));
}
/**
* @param d The {@link Digest} to use
* @param buf The data buffer to be fingerprint-ed
* @param offset The offset of the data in the buffer
* @param len The length of data - ignored if non-positive
* @return The fingerprint - {@code null} if non-positive length
* @throws Exception If failed to calculate the fingerprint
* @see #getRawFingerprint(Digest, byte[], int, int)
*/
public static String getFingerPrint(Digest d, byte[] buf, int offset, int len) throws Exception {
if (len <= 0) {
return null;
}
byte[] data = getRawFingerprint(d, buf, offset, len);
String algo = d.getAlgorithm();
if (BuiltinDigests.md5.getAlgorithm().equals(algo)) {
return algo + ":" + BufferUtils.toHex(':', data).toLowerCase();
}
Base64.Encoder encoder = Base64.getEncoder();
return algo.replace("-", "").toUpperCase() + ":" + encoder.encodeToString(data).replaceAll("=", "");
}
public static byte[] getRawFingerprint(Digest d, byte... buf) throws Exception {
return getRawFingerprint(d, buf, 0, NumberUtils.length(buf));
}
public static byte[] getRawFingerprint(Digest d, byte[] buf, int offset, int len) throws Exception {
if (len <= 0) {
return null;
}
Objects.requireNonNull(d, "No digest").init();
d.update(buf, offset, len);
return d.digest();
}
}