Интервьюер: Расскажите мне о вашем обычно используемом алгоритме шифрования.

интервью

Алгоритмы шифрования можно разделить на: обратимое шифрование и необратимое шифрование, а обратимое шифрование можно разделить на: симметричное шифрование и асимметричное шифрование.

1. Необратимое шифрование

Общие алгоритмы необратимого шифрованияMD5,HMAC,SHA1,SHA-224,SHA-256,SHA-384SHA-512SHA-224,SHA-256,SHA-384SHA-512мы можем коллективно позвонитьSHA2алгоритм шифрования,SHAАлгоритмы шифрования более безопасны, чемMD5выше, при этомSHA2отношение алгоритма шифрованияSHA1выше. вSHAСледующие числа указывают длину зашифрованной строки,SHA1По умолчанию160Сводная информация о битах.

Самой большой особенностью алгоритма необратимого шифрования является ключ, ноHMACЭто [ручная собачья голова], для которой нужен ключ.

Поскольку эти шифрования необратимы, наиболее часто используемый сценарий — это шифрование пароля пользователя, а процесс проверки заключается в подтверждении личности путем сравнения двух зашифрованных строк. Есть также много онлайн, которые утверждают, что их можно взломать.MD5Принцип сайта паролей тот же, то есть есть огромная библиотека ресурсов, в которой хранится множество строк и соответствующихMD5Зашифрованная строка через ваш вводMD5Зашифрованные строки для сравнения, если сложность вашего пароля относительно невелика, все еще существует высокая вероятность проверки.

1.1 MD5

Алгоритм дайджеста сообщения MD5(английский: MD5 Message-Digest Algorithm), широко используемая криптографическая хеш-функция, которая генерирует 128-битное (16-байтовое) хеш-значение для обеспечения полной и согласованной передачи информации.

MD5Алгоритм имеет следующие характеристики:

1. Сжимаемость: независимо от длины данных вычисляетсяMD5Значения имеют одинаковую длину

2. Простота расчета: легко рассчитать по исходным данным.MD5ценность

3. Устойчивость к модификации: даже если один байт изменен, расчетноеMD5значения будут сильно различаться

4. Сопротивление столкновениям: знайте данные иMD5значение, с небольшой вероятностью найти то же самоеMD5исходные данные с тем же значением.

public static String md5(String text) {
    MessageDigest messageDigest = null;
    try {
        messageDigest = MessageDigest.getInstance("MD5");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    byte[] bytes = messageDigest.digest(text.getBytes());
    return Hex.encodeHexString(bytes); 
}

1.2 Серия ША

Алгоритм безопасного хеширования(англ. Secure Hash Algorithm, сокращенно SHA) — это семейство криптографических хеш-функций и безопасный хеш-алгоритм, сертифицированный FIPS. Алгоритм, который может вычислить строку фиксированной длины (также называемую дайджестом сообщения), соответствующую цифровому сообщению. А если входные сообщения разные, то велика вероятность, что они соответствуют разным строкам.

В конце конференции CRYPTO 17 августа 2005 года Ван Сяоюнь, Яо Цичжи и Яо Чуфэн в очередной раз опубликовали более эффективный метод атаки SHA-1, который может находить коллизии в пределах вычислительной сложности 2 в 63-й степени.

то естьSHA-1Алгоритмы шифрования имеют возможность коллизий, хотя и небольшую.

public static String sha256(String text) {
    MessageDigest messageDigest = null;
    try {
        messageDigest = MessageDigest.getInstance("SHA-256");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    byte[] bytes = messageDigest.digest(text.getBytes()); 
    return Hex.encodeHexString(bytes); 
}

1.3 Серия HMAC

HMAC — это аббревиатура от Hash-based Message Authentication Code (Hash-based Message Authentication Code), относящаяся к ключевому методу аутентификации и опубликованная в 1997 году как RFC2104 иIPSecи другие сетевые протоколы, такие какSSL) широко используется и в настоящее время стал стандартом безопасности в Интернете де-факто. Его можно связать с любой итеративной хэш-функцией.

Алгоритм HMAC больше похож на алгоритм шифрования, который вводит ключ, и его безопасность не полностью зависит от используемого алгоритма хеширования.

public static String hmacSha256(String text, SecretKeySpec sk) {
    Mac mac = null;
    try {
        mac = Mac.getInstance("HmacSHA256");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    try {
        mac.init(sk);
    } catch (InvalidKeyException e) {
        e.printStackTrace();
    }
    byte[] rawHmac = mac.doFinal(text.getBytes());
    return new String(Base64.encodeBase64(rawHmac));
}

Если вы хотите использовать необратимое шифрование, рекомендуется использовать алгоритмы SHA256, SHA384, SHA512 и HMAC-SHA256, HMAC-SHA384, HMAC-SHA512.

2. Алгоритм симметричного шифрования

Алгоритм симметричного шифрования является относительно ранним алгоритмом, и для шифрования и дешифрования данных используется один и тот же ключ, что вызывает проблему сложного управления ключами. Общие алгоритмы симметричного шифрованияDES,3DES,AES128,AES192,AES256(устанавливается по умолчаниюJDKПока не поддерживаетсяAES256, необходимо установить соответствующийjceПатч для обновленияjce1.7,jce1.8). вAESСледующее число представляет длину ключа. Безопасность алгоритма симметричного шифрования относительно низка, и более применимым сценарием является шифрование и дешифрование в среде интрасети.

2.1 DES

DESявляется типичным алгоритмом в области алгоритмов симметричного шифрования, а длина ключа по умолчанию равна56немного.

// 加密
public static String encrypt(byte[] dataSource, String password){
     try {
         SecureRandom random = new SecureRandom();
         DESKeySpec desKeySpec = new DESKeySpec(password.getBytes());
         //创建一个密匙工厂,然后用它把DESKeySpec转换成 
         SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES"); 
         SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec); 
         //Cipher对象实际完成加密操作 
         Cipher cipher = Cipher.getInstance("DES"); 
         //用密匙初始化Cipher对象 
         cipher.init(Cipher.ENCRYPT_MODE, secretKey, random); 
         //正式执行加密操作 
         return Base64.encodeBase64String(cipher.doFinal(dataSource)); 
     } catch (Throwable e) { 
         e.printStackTrace(); 
     } return null; 
 } 
// 解密
public static String decrypt(String src, String password) throws Exception{ 
    // DES算法要求有一个可信任的随机数源 
    SecureRandom random = new SecureRandom(); 
    // 创建一个DESKeySpec对象 
    DESKeySpec desKeySpec = new DESKeySpec(password.getBytes()); 
    // 创建一个密匙工厂 
    SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES"); 
    // 将DESKeySpec对象转换成SecretKey对象 
    SecretKey secretKey = keyFactory.generateSecret(desKeySpec); 
    // Cipher对象实际完成解密操作 
    Cipher cipher = Cipher.getInstance("DES"); 
    // 用密匙初始化Cipher对象 
    cipher.init(Cipher.DECRYPT_MODE, secretKey, random); 
    // 真正开始解密操作 
    return new String(cipher.doFinal(Base64.decodeBase64(src))); 
}

2.2 3DES

3DES(т.е. Тройной DES)DESВ направленииAESАлгоритм переходного шифрования, использующий три 56-битных ключа для трехкратного шифрования данных. даDESБолее безопасный вариант . это начинается сDESВ качестве базового модуля алгоритм блочного шифрования разработан путем комбинирования метода группировки. чем оригиналDES,3DESБезопаснее. Длина ключа по умолчанию равна168бит, вы также можете выбрать128немного.

public static String encryptThreeDESECB(String src, String key) {
    try{
        DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
        SecretKey securekey = keyFactory.generateSecret(dks);

        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, securekey);
        byte[] b = cipher.doFinal(src.getBytes("UTF-8"));

        String ss = new String(Base64.encodeBase64(b));
        ss = ss.replaceAll("\\+", "-");
        ss = ss.replaceAll("/", "_");
        return ss;
    } catch(Exception ex){
        ex.printStackTrace();
        return src;
    }
}

public static String decryptThreeDESECB(String src, String key) {
    try{
        src = src.replaceAll("-", "+");
        src = src.replaceAll("_", "/");
        byte[] bytesrc = Base64.decodeBase64(src.getBytes("UTF-8"));
        // --解密的key
        DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
        SecretKey securekey = keyFactory.generateSecret(dks);

        // --Chipher对象解密
        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, securekey);
        byte[] retByte = cipher.doFinal(bytesrc);

        return new String(retByte, "UTF-8");
    } catch(Exception ex){
        ex.printStackTrace();
        return src;
    }
}

2.3 AES

AESУсовершенствованный стандарт шифрования данных, эффективный против известныхDESВсе атаки на алгоритм, длина ключа по умолчанию128биты, также по желанию192немного,256немного. Здесь, кстати, этот бит относится к биту.

private static final String defaultCharset = "UTF-8";
private static final String KEY_AES = "AES";
private static final String KEY_MD5 = "MD5";
private static MessageDigest md5Digest;
static {
    try {
        md5Digest = MessageDigest.getInstance(KEY_MD5);
    } catch (NoSuchAlgorithmException e) {

    }
}
/**
  * 加密
  */
public static String encrypt(String data, String key) {
    return doAES(data, key, Cipher.ENCRYPT_MODE);
}
/**
  * 解密
  */
public static String decrypt(String data, String key) {
    return doAES(data, key, Cipher.DECRYPT_MODE);
}


/**
  * 加解密
  */
private static String doAES(String data, String key, int mode) {
    try {
        boolean encrypt = mode == Cipher.ENCRYPT_MODE;
        byte[] content;
        if (encrypt) {
            content = data.getBytes(defaultCharset);
        } else {
            content = Base64.decodeBase64(data.getBytes());
        }
        SecretKeySpec keySpec = new SecretKeySpec(md5Digest.digest(key.getBytes(defaultCharset))
                                                  , KEY_AES);
        Cipher cipher = Cipher.getInstance(KEY_AES);// 创建密码器
        cipher.init(mode, keySpec);// 初始化
        byte[] result = cipher.doFinal(content);
        if (encrypt) {
            return new String(Base64.encodeBase64(result));
        } else {
            return new String(result, defaultCharset);
        }
    } catch (Exception e) {
    }
    return null;
}

Рекомендуемые алгоритмы симметричного шифрования:AES128,AES192,AES256.

3. Алгоритм асимметричного шифрования

Алгоритмы асимметричного шифрования имеют два ключа, которые совершенно разные, но точно совпадают. Шифрование и дешифрование открытого текста может быть выполнено только с использованием совпадающей пары открытого и закрытого ключей. Обычные асимметричные шифрыRSA,SM2Ждать.

3.1 RSA

RSAКлюч должен иметь длину не менее 500 бит, обычно рекомендуется 1024 бита.

//非对称密钥算法
public static final String KEY_ALGORITHM = "RSA";

/**
  * 密钥长度,DH算法的默认密钥长度是1024
  * 密钥长度必须是64的倍数,在512到65536位之间
  */
private static final int KEY_SIZE = 1024;
//公钥
private static final String PUBLIC_KEY = "RSAPublicKey";
//私钥
private static final String PRIVATE_KEY = "RSAPrivateKey";
/**
  * 初始化密钥对
  *
  * @return Map 甲方密钥的Map
  */
public static Map<String, Object> initKey() throws Exception {
    //实例化密钥生成器
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORITHM);
    //初始化密钥生成器
    keyPairGenerator.initialize(KEY_SIZE);
    //生成密钥对
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    //甲方公钥
    RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
    //甲方私钥
    RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
    //将密钥存储在map中
    Map<String, Object> keyMap = new HashMap<String, Object>();
    keyMap.put(PUBLIC_KEY, publicKey);
    keyMap.put(PRIVATE_KEY, privateKey);
    return keyMap;
}
/**
  * 私钥加密
  *
  * @param data 待加密数据
  * @param key  密钥
  * @return byte[] 加密数据
  */
public static byte[] encryptByPrivateKey(byte[] data, byte[] key) throws Exception {

    //取得私钥
    PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    //生成私钥
    PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
    //数据加密
    Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.ENCRYPT_MODE, privateKey);
    return cipher.doFinal(data);
}

/**
  * 公钥加密
  *
  * @param data 待加密数据
  * @param key  密钥
  * @return byte[] 加密数据
  */
public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws Exception {

    //实例化密钥工厂
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    //初始化公钥
    //密钥材料转换
    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
    //产生公钥
    PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
    //数据加密
    Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.ENCRYPT_MODE, pubKey);
    return cipher.doFinal(data);
}

/**
  * 私钥解密
  *
  * @param data 待解密数据
  * @param key  密钥
  * @return byte[] 解密数据
  */
public static byte[] decryptByPrivateKey(byte[] data, byte[] key) throws Exception {
    //取得私钥
    PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(key);
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    //生成私钥
    PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
    //数据解密
    Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    return cipher.doFinal(data);
}

/**
  * 公钥解密
  *
  * @param data 待解密数据
  * @param key  密钥
  * @return byte[] 解密数据
  */
public static byte[] decryptByPublicKey(byte[] data, byte[] key) throws Exception {

    //实例化密钥工厂
    KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
    //初始化公钥
    //密钥材料转换
    X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(key);
    //产生公钥
    PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
    //数据解密
    Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
    cipher.init(Cipher.DECRYPT_MODE, pubKey);
    return cipher.doFinal(data);
}

/**
  * 取得私钥
  *
  * @param keyMap 密钥map
  * @return byte[] 私钥
  */
public static byte[] getPrivateKey(Map<String, Object> keyMap) {
    Key key = (Key) keyMap.get(PRIVATE_KEY);
    return key.getEncoded();
}

/**
  * 取得公钥
  *
  * @param keyMap 密钥map
  * @return byte[] 公钥
  */
public static byte[] getPublicKey(Map<String, Object> keyMap) throws Exception {
    Key key = (Key) keyMap.get(PUBLIC_KEY);
    return key.getEncoded();
}

В-четвертых, шифровальная соль

Также часто можно услышать понятие «соль шифрования».Соль — это случайная строка, используемая для ее шифрования после сращивания с нашей зашифрованной строкой. Основная цель добавления соли — обеспечить безопасность зашифрованных строк. Если имеется зашифрованная строка с солью, и хакер использует эту зашифрованную строку определенным образом, открытый текст, который он получает, представляет собой не строку до шифрования, а строку, объединенную со строкой до шифрования и солью. строка снова.

Некоторые алгоритмы в этой статье получены из сети и могут быть напрямую скопированы и использованы..

Несколько рекомендуемых алгоритмов шифрования:

  • Необратимое шифрование:SHA256,SHA384,SHA512а такжеHMAC-SHA256,HMAC-SHA384,HMAC-SHA512
  • Алгоритм симметричного шифрования:AES,3DES
  • Алгоритм асимметричного шифрования:RSA