Аннотация
Это первая из трех статей блога, посвященных криптографическим алгоритмам Java. В серии рассказывается, как реализовать следующее:
- Хеширование с помощью SHA – 512
- Симметричное шифрование с одним ключом с помощью AES – 256
- Асимметричное шифрование с открытым / закрытым ключом с помощью RSA – 4096
В этом первом посте подробно описывается, как реализовать хеширование SHA-512. Давайте начнем.
отказ
Этот пост является исключительно информативным. Критически подумайте, прежде чем использовать любую представленную информацию. Учитесь на этом, но в конечном итоге принимайте свои собственные решения на свой страх и риск.
Требования
Я сделал всю работу для этого поста, используя следующие основные технологии. Вы можете сделать то же самое с разными технологиями или версиями, но без гарантий.
- Java 1.8.0_152_x64
- NetBeans 8.2 (сборка 201609300101)
- Maven 3.0.5 (в комплекте с NetBeans)
Скачать
Посетите мою страницу GitHub, чтобы увидеть все мои проекты с открытым исходным кодом. Код для этого поста находится в проекте: thoth-cryptography
Хэш
Около
Хеширование — это односторонний криптографический алгоритм, который принимает сообщение любой длины и выдает повторяемый, фиксированный по длине и односторонний дайджест (хэш) сообщения. Будучи односторонним, предполагается, что невозможно восстановить исходное сообщение из хэша. Одинаковые сообщения всегда будут генерировать один и тот же хэш.
Хеш может использоваться для аутентификации исходного сообщения. Обычное использование хеширования — проверка паролей. Вместо хранения самого пароля сохраняется хеш пароля. Для проверки пароля сохраненный хеш сравнивается с новым хешем входящего пароля во время процесса входа в систему.
Поскольку идентичные сообщения генерируют один и тот же хэш, для повышения его безопасности используется солт-значение (Salt, 2017, пункт 1). Рассмотрим случай, когда один и тот же пароль используется несколькими пользователями. Солт-значение в сочетании с исходным паролем допускает уникальные значения хеш-функции. Это важно, потому что если хэшированные значения когда-либо скомпрометированы, идентичные хеши позволяют хакеру узнать, что эти пароли одинаковы.
SHA-512
Исследования, проведенные на сегодняшний день, показывают, что лучшим и наиболее безопасным алгоритмом хеширования является SHA-512, в котором используются 64-битные слова (Secure Hash Algorithms, 2017, пункт 2). Давайте посмотрим на пример.
ПРИМЕЧАНИЕ. Не используйте MD5 в качестве безопасного хэша. У него много уязвимостей (MD5, 2017, пункт 1). Ограничьте использование MD5 контрольными суммами и проверкой данных.
пример
В листинге 1 приведен модульный тест ShaTest.java, демонстрирующий, как хэшировать. В листинге 2 приведен класс Sha.java, который выполняет хэширование.
Листинг 1 — класс ShaTest.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
package org.thoth.security.hash;import java.util.Optional;import org.junit.Assert;import org.junit.Test;/** * @author Michael Remijan mjremijan@yahoo.com @mjremijan */public class ShaTest { @Test public void test_hash_with_optional_to_hex() throws Exception { // setup String username = "mjremijan"; String password = "super!secret"; Sha sha = new Sha(); // test String asHex = sha.hashToHex(password, Optional.of(username)); // assert Assert.assertEquals( "F38CD5290D11B20159E36740843A8D93CFDFA395CF594F328613EF5C7BA42D9EAC00BF3EE47B7E8CE1587040B36365F05C8E15E9392C288A1D7C4CFB66097848" , asHex); } @Test public void test_hash_without_optional_to_hex() throws Exception { // setup String password = "super!secret"; Sha sha = new Sha(); // test String asHex = sha.hashToHex(password, Optional.empty()); // assert Assert.assertEquals( "516A1FE9D87FE5B953D91B48B1A2FFA5AE5F670914C1B6FE0835D8877918DC4E8BC8FB8CCD520DBA940C21B4F294DFD1B4EFF2E06AB110C6A06E35068251C1DD" , asHex); } @Test public void test_hash_with_optional_to_base64() throws Exception { // setup String username = "mjremijan"; String password = "super!secret"; Sha sha = new Sha(); // test String asBase64 = sha.hashToBase64(password, Optional.of(username)); // assert Assert.assertEquals( "84ZVKQ0RSGFZ42DAHDQNK8/FO5XPWU8YHHPVXHUKLZ6SAL8+5HT+JOFYCECZY2XWXI4V6TKSKIODFEZ7ZGL4SA==" , asBase64); } @Test public void test_hash_without_optional_to_base64() throws Exception { // setup String password = "super!secret"; Sha sha = new Sha(); // test String asBase64 = sha.hashToBase64(password, Optional.empty()); // assert Assert.assertEquals( "UWOF6DH/5BLT2RTISAL/PA5FZWKUWBB+CDXYH3KY3E6LYPUMZVINUPQMIBTYLN/RTO/Y4GQXEMAGBJUGGLHB3Q==" , asBase64); }} |
Листинг 2 — Класс Sha.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package org.thoth.security.hash;import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.Base64;import java.util.Optional;/** * @author Michael Remijan mjremijan@yahoo.com @mjremijan */public class Sha { public String hashToHex(String hashMe, Optional<String> salt) throws NoSuchAlgorithmException, UnsupportedEncodingException { byte[] bytes = hash(hashMe, salt); StringBuilder sp = new StringBuilder(); for (int i = 0; i < bytes.length; i++) { sp.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1)); } return sp.toString().toUpperCase(); } public String hashToBase64(String hashMe, Optional<String> salt) throws NoSuchAlgorithmException, UnsupportedEncodingException { return Base64.getEncoder().encodeToString( hash(hashMe, salt) ).toUpperCase(); } public byte[] hash(String hashMe, Optional<String> salt) throws NoSuchAlgorithmException, UnsupportedEncodingException { MessageDigest md = MessageDigest.getInstance("SHA-512"); md.update(hashMe.getBytes("UTF-8")); salt.ifPresent(s -> { try { md.update(s.getBytes("UTF-8")); } catch (Exception e) {throw new RuntimeException(e);} }); return md.digest(); }} |
Резюме
Хеширование довольно легко. Выберите надежный алгоритм хеширования, такой как SHA-512, для защиты данных вашего приложения. Избегайте MD5 для защиты данных. Будьте в курсе, какие алгоритмы сильны и безопасны. Обновите приложение, если вы используете более старый алгоритм, который имеет уязвимости или скомпрометирован.
Рекомендации
Соль (криптография). (2017, 3 ноября). Wikipedia. Получено с https://en.wikipedia.org/wiki/Salt_(cryptography) .
Безопасные алгоритмы хеширования. (2017, 25 ноября). Wikipedia. Получено с https://en.wikipedia.org/wiki/Secure_Hash_Algorithms .
MD5. (2017, 22 ноября). Wikipedia. Получено с https://en.wikipedia.org/wiki/MD5 .
|
Опубликовано на Java Code Geeks с разрешения Майкла Ремиджана, партнера нашей программы JCG. См. Оригинальную статью здесь: Выбор алгоритмов шифрования Java. Часть 1. Хеширование. Мнения, высказанные участниками Java Code Geeks, являются их собственными. |