mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-11-04 09:40:05 +01:00
Add tools task to generate an encryption algorithm overview
This commit is contained in:
parent
a0da423a7b
commit
6475cecd79
@ -10,8 +10,6 @@ import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@HasSalt(SaltType.USERNAME)
|
||||
public class CRAZYCRYPT1 extends UsernameSaltMethod {
|
||||
|
||||
private static final char[] CRYPTCHARS =
|
||||
|
@ -8,7 +8,7 @@ import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
import static fr.xephi.authme.security.HashUtils.md5;
|
||||
|
||||
@Recommendation(Usage.DO_NOT_USE)
|
||||
@Recommendation(Usage.ACCEPTABLE)
|
||||
@HasSalt(value = SaltType.TEXT, length = 5)
|
||||
public class IPB3 extends SeparateSaltMethod {
|
||||
|
||||
|
@ -1,9 +1,15 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
import static fr.xephi.authme.security.HashUtils.md5;
|
||||
|
||||
@Recommendation(Usage.ACCEPTABLE)
|
||||
@HasSalt(value = SaltType.TEXT, length = 8)
|
||||
public class MYBB extends SeparateSaltMethod {
|
||||
|
||||
@Override
|
||||
|
@ -1,9 +1,15 @@
|
||||
package fr.xephi.authme.security.crypts;
|
||||
|
||||
import fr.xephi.authme.security.RandomString;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
import static fr.xephi.authme.security.HashUtils.sha1;
|
||||
|
||||
@Recommendation(Usage.ACCEPTABLE)
|
||||
@HasSalt(value = SaltType.TEXT, length = 40)
|
||||
public class WBB3 extends SeparateSaltMethod {
|
||||
|
||||
@Override
|
||||
|
78
src/tools/docs/hash_algorithms.md
Normal file
78
src/tools/docs/hash_algorithms.md
Normal file
@ -0,0 +1,78 @@
|
||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||
<!-- File auto-generated on Thu Dec 31 13:26:54 CET 2015. See hashmethods/hash_algorithms.tpl.md -->
|
||||
|
||||
## Hash Algorithms
|
||||
AuthMe supports the following hash algorithms for storing your passwords safely.
|
||||
|
||||
|
||||
Algorithm | Recommendation | Hash length | ASCII | | Salt type | Length | Separate? |
|
||||
--------- | -------------- | ----------- | ----- | - | --------- | ------ | --------- |
|
||||
BCRYPT | Recommended | 60 | | | Text | |
|
||||
BCRYPT2Y | Recommended | 60 | | | Text | 22 |
|
||||
CRAZYCRYPT1 | Do not use | 128 | | | Username | |
|
||||
DOUBLEMD5 | Do not use | 32 | | | None | |
|
||||
IPB3 | Acceptable | 32 | | | Text | 5 | Y
|
||||
JOOMLA | Recommended | 65 | | | Text | 32 |
|
||||
MD5 | Do not use | 32 | | | None | |
|
||||
MD5VB | Acceptable | 56 | | | Text | 16 |
|
||||
MYBB | Acceptable | 32 | | | Text | 8 | Y
|
||||
PBKDF2 | Does not work | 329 | | | Text | 12 |
|
||||
PBKDF2DJANGO | Acceptable | 77 | Y | | Text | 12 |
|
||||
PHPBB | Acceptable | 34 | | | Text | 16 |
|
||||
PHPFUSION | Do not use | 64 | Y | | | | Y
|
||||
ROYALAUTH | Do not use | 128 | | | None | |
|
||||
SALTED2MD5 | Acceptable | 32 | | | Text | | Y
|
||||
SALTEDSHA512 | Recommended | 128 | | | | | Y
|
||||
SHA1 | Do not use | 40 | | | None | |
|
||||
SHA256 | Recommended | 86 | | | Text | 16 |
|
||||
SHA512 | Do not use | 128 | | | None | |
|
||||
SMF | Do not use | 40 | | | Username | |
|
||||
WBB3 | Acceptable | 40 | | | Text | 40 | Y
|
||||
WBB4 | Does not work | 60 | | | Text | 8 |
|
||||
WHIRLPOOL | Do not use | 128 | | | None | |
|
||||
WORDPRESS | Do not use | 34 | | | Text | 9 |
|
||||
XAUTH | Recommended | 140 | | | Text | 12 |
|
||||
CUSTOM | | | | | | | |
|
||||
|
||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||
|
||||
### Columns
|
||||
#### Algorithm
|
||||
The algorithm is the hashing algorithm used to store passwords with. Default is SHA256 and is recommended.
|
||||
You can change the hashing algorithm in the config.yml: under `security`, locate `passwordHash`.
|
||||
|
||||
#### Recommendation
|
||||
The recommendation lists our usage recommendation in terms of how secure it is (not how _well_ the algorithm works!).
|
||||
- Recommended: The hash algorithm appears to be cryptographically secure and is one we recommend.
|
||||
- Acceptable: There are safer algorithms that can be chosen but using the algorithm is generally OK.
|
||||
- Do not use: Hash algorithm isn't sufficiently secure. Use only if required to hook into another system.
|
||||
- Does not work: The algorithm does not work properly; do not use.
|
||||
|
||||
#### Hash Length
|
||||
The length of the hashes the algorithm produces. Note that the hash length is not (primarily) indicative of
|
||||
whether an algorithm is secure or not.
|
||||
|
||||
#### ASCII
|
||||
If denoted with a **y**, means that the algorithm is restricted to ASCII characters only, i.e. it will simply ignore
|
||||
"special characters" such as `ÿ` or `Â`. Note that we do not recommend the use of "special characters" in passwords.
|
||||
|
||||
#### Salt Columns
|
||||
Before hashing, a _salt_ may be appended to the password to make the hash more secure. The following columns describe
|
||||
the salt the algorithm uses.
|
||||
<!-- AUTO-GENERATED FILE! Do not edit this directly -->
|
||||
|
||||
##### Salt Type
|
||||
We do not recommend the usage
|
||||
of any algorithm that doesn't use a randomly generated text as salt. This "salt type" column indicates what type of
|
||||
salt the algorithm uses:
|
||||
- Text: randomly generated text (see also the following column, "Length")
|
||||
- Username: the salt is constructed from the username (bad)
|
||||
- None: the algorithm uses no salt (bad)
|
||||
|
||||
##### Length
|
||||
If applicable (salt type is "Text"), indicates the length of the generated salt. The longer the better.
|
||||
If this column is empty when the salt type is "Text", it typically means the salt length can be defined in config.yml.
|
||||
|
||||
##### Separate
|
||||
If denoted with a **y**, it means that the salt is stored in a separate column in the database. This is neither good
|
||||
or bad.
|
135
src/tools/hashmethods/EncryptionMethodInfoGatherer.java
Normal file
135
src/tools/hashmethods/EncryptionMethodInfoGatherer.java
Normal file
@ -0,0 +1,135 @@
|
||||
package hashmethods;
|
||||
|
||||
import fr.xephi.authme.security.HashAlgorithm;
|
||||
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||
import fr.xephi.authme.security.crypts.HexSaltedMethod;
|
||||
import fr.xephi.authme.security.crypts.description.AsciiRestricted;
|
||||
import fr.xephi.authme.security.crypts.description.HasSalt;
|
||||
import fr.xephi.authme.security.crypts.description.Recommendation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.collect.Sets.newHashSet;
|
||||
|
||||
/**
|
||||
* Gathers information on {@link fr.xephi.authme.security.crypts.EncryptionMethod} implementations based on
|
||||
* the annotations in {@link fr.xephi.authme.security.crypts.description}.
|
||||
*/
|
||||
public class EncryptionMethodInfoGatherer {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final static Set<Class<? extends Annotation>> RELEVANT_ANNOTATIONS =
|
||||
newHashSet(HasSalt.class, Recommendation.class, AsciiRestricted.class);
|
||||
|
||||
private Map<HashAlgorithm, MethodDescription> descriptions;
|
||||
|
||||
public EncryptionMethodInfoGatherer() {
|
||||
descriptions = new LinkedHashMap<>();
|
||||
constructDescriptions();
|
||||
}
|
||||
|
||||
public Map<HashAlgorithm, MethodDescription> getDescriptions() {
|
||||
return descriptions;
|
||||
}
|
||||
|
||||
private void constructDescriptions() {
|
||||
for (HashAlgorithm algorithm : HashAlgorithm.values()) {
|
||||
Class<? extends EncryptionMethod> methodClazz = algorithm.getClazz();
|
||||
if (!HashAlgorithm.CUSTOM.equals(algorithm) && !methodClazz.isAnnotationPresent(Deprecated.class)) {
|
||||
MethodDescription description = createDescription(methodClazz);
|
||||
descriptions.put(algorithm, description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodDescription createDescription(Class<? extends EncryptionMethod> clazz) {
|
||||
EncryptionMethod method = instantiateMethod(clazz);
|
||||
MethodDescription description = new MethodDescription(clazz);
|
||||
description.setHashLength(method.computeHash("test", "user").getHash().length());
|
||||
description.setHasSeparateSalt(method.hasSeparateSalt());
|
||||
|
||||
Map<Class<?>, Annotation> annotationMap = gatherAnnotations(clazz);
|
||||
if (annotationMap.containsKey(HasSalt.class)) {
|
||||
setSaltInformation(description, returnTyped(annotationMap, HasSalt.class), method);
|
||||
}
|
||||
if (annotationMap.containsKey(Recommendation.class)) {
|
||||
description.setUsage(returnTyped(annotationMap, Recommendation.class).value());
|
||||
}
|
||||
if (annotationMap.containsKey(AsciiRestricted.class)) {
|
||||
description.setAsciiRestricted(true);
|
||||
}
|
||||
return description;
|
||||
}
|
||||
|
||||
private static Map<Class<?>, Annotation> gatherAnnotations(Class<?> methodClass) {
|
||||
// Note ljacqu 20151231: The map could be Map<Class<? extends Annotation>, Annotation> and it has the constraint
|
||||
// that for a key Class<T>, the value is of type T. We write a simple "Class<?>" for brevity.
|
||||
Map<Class<?>, Annotation> collection = new HashMap<>();
|
||||
Class<?> currentMethodClass = methodClass;
|
||||
while (currentMethodClass != null) {
|
||||
getRelevantAnnotations(currentMethodClass, collection);
|
||||
currentMethodClass = getSuperClass(currentMethodClass);
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
// Parameters could be Class<? extends EncryptionMethod>; Map<Class<? extends Annotation>, Annotation>
|
||||
// but the constraint doesn't have any technical relevance, so just clutters the code
|
||||
private static void getRelevantAnnotations(Class<?> methodClass, Map<Class<?>, Annotation> collection) {
|
||||
for (Annotation annotation : methodClass.getAnnotations()) {
|
||||
if (RELEVANT_ANNOTATIONS.contains(annotation.annotationType())
|
||||
&& !collection.containsKey(annotation.annotationType())) {
|
||||
collection.put(annotation.annotationType(), annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the super class of the given encryption method if it is also of EncryptionMethod type.
|
||||
* (Anything beyond EncryptionMethod is not of interest.)
|
||||
*/
|
||||
private static Class<?> getSuperClass(Class<?> methodClass) {
|
||||
Class<?> zuper = methodClass.getSuperclass();
|
||||
if (EncryptionMethod.class.isAssignableFrom(zuper)) {
|
||||
return zuper;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the salt information for the given encryption method and the found {@link HasSalt} annotation.
|
||||
* Also gets the salt length from {@link HexSaltedMethod#getSaltLength()} for such instances.
|
||||
*
|
||||
* @param description The description to update
|
||||
* @param hasSalt The associated HasSalt annotation
|
||||
* @param method The encryption method
|
||||
*/
|
||||
private static void setSaltInformation(MethodDescription description, HasSalt hasSalt, EncryptionMethod method) {
|
||||
description.setSaltType(hasSalt.value());
|
||||
if (hasSalt.length() != 0) {
|
||||
description.setSaltLength(hasSalt.length());
|
||||
} else if (method instanceof HexSaltedMethod) {
|
||||
int saltLength = ((HexSaltedMethod) method).getSaltLength();
|
||||
description.setSaltLength(saltLength);
|
||||
}
|
||||
}
|
||||
|
||||
private static EncryptionMethod instantiateMethod(Class<? extends EncryptionMethod> clazz) {
|
||||
try {
|
||||
return clazz.newInstance();
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
throw new RuntimeException("Could not instantiate " + clazz, e);
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience method for retrieving an annotation in a typed fashion.
|
||||
// We know implicitly that the key of the map always corresponds to the type of the value
|
||||
private static <T> T returnTyped(Map<Class<?>, Annotation> map, Class<T> key) {
|
||||
return key.cast(map.get(key));
|
||||
}
|
||||
|
||||
}
|
100
src/tools/hashmethods/HashAlgorithmsDescriptionTask.java
Normal file
100
src/tools/hashmethods/HashAlgorithmsDescriptionTask.java
Normal file
@ -0,0 +1,100 @@
|
||||
package hashmethods;
|
||||
|
||||
import fr.xephi.authme.security.HashAlgorithm;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.util.WrapperMock;
|
||||
import utils.ANewMap;
|
||||
import utils.FileUtils;
|
||||
import utils.TagReplacer;
|
||||
import utils.ToolTask;
|
||||
import utils.ToolsConstants;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* Task for generating the markdown page describing the AuthMe hash algorithms.
|
||||
*
|
||||
* @see {@link fr.xephi.authme.security.HashAlgorithm}
|
||||
*/
|
||||
public class HashAlgorithmsDescriptionTask implements ToolTask {
|
||||
|
||||
private static final String CUR_FOLDER = ToolsConstants.TOOLS_SOURCE_ROOT + "hashmethods/";
|
||||
private static final String OUTPUT_FILE = ToolsConstants.DOCS_FOLDER + "hash_algorithms.md";
|
||||
|
||||
@Override
|
||||
public void execute(Scanner scanner) {
|
||||
// Unfortunately, we need the Wrapper to be around to work with Settings, and certain encryption methods
|
||||
// directly read from the Settings file
|
||||
WrapperMock.createInstance();
|
||||
Settings.bCryptLog2Rounds = 8;
|
||||
Settings.saltLength = 8;
|
||||
|
||||
// Gather info and construct a row for each method
|
||||
EncryptionMethodInfoGatherer infoGatherer = new EncryptionMethodInfoGatherer();
|
||||
Map<HashAlgorithm, MethodDescription> descriptions = infoGatherer.getDescriptions();
|
||||
final String methodRows = constructMethodRows(descriptions);
|
||||
|
||||
// Write to the docs file
|
||||
Map<String, String> tags = ANewMap.with("method_rows", methodRows).build();
|
||||
FileUtils.generateFileFromTemplate(CUR_FOLDER + "hash_algorithms.tpl.md", OUTPUT_FILE, tags);
|
||||
}
|
||||
|
||||
private static String constructMethodRows(Map<HashAlgorithm, MethodDescription> descriptions) {
|
||||
final String rowTemplate = FileUtils.readFromFile(CUR_FOLDER + "hash_algorithms_row.tpl.md");
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (Map.Entry<HashAlgorithm, MethodDescription> entry : descriptions.entrySet()) {
|
||||
MethodDescription description = entry.getValue();
|
||||
Map<String, String> tags = ANewMap
|
||||
.with("name", asString(entry.getKey()))
|
||||
.and("recommendation", asString(description.getUsage()))
|
||||
.and("hash_length", asString(description.getHashLength()))
|
||||
.and("ascii_restricted", asString(description.isAsciiRestricted()))
|
||||
.and("salt_type", asString(description.getSaltType()))
|
||||
.and("salt_length", asString(description.getSaltLength()))
|
||||
.and("separate_salt", asString(description.hasSeparateSalt()))
|
||||
.build();
|
||||
result.append(TagReplacer.applyReplacements(rowTemplate, tags));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTaskName() {
|
||||
return "describeHashAlgos";
|
||||
}
|
||||
|
||||
// ----
|
||||
// String representations
|
||||
// ----
|
||||
private static String asString(boolean value) {
|
||||
return value ? "Y" : "";
|
||||
}
|
||||
|
||||
private static String asString(int value) {
|
||||
return String.valueOf(value);
|
||||
}
|
||||
|
||||
private static String asString(Integer value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
return String.valueOf(value);
|
||||
}
|
||||
|
||||
private static String asString(HashAlgorithm value) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
private static <E extends Enum<E>> String asString(E value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
// Get the enum name and replace something like "DO_NOT_USE" to "Do not use"
|
||||
String enumName = value.toString().replace("_", " ");
|
||||
return enumName.length() > 2
|
||||
? enumName.substring(0, 1) + enumName.substring(1).toLowerCase()
|
||||
: enumName;
|
||||
}
|
||||
|
||||
}
|
85
src/tools/hashmethods/MethodDescription.java
Normal file
85
src/tools/hashmethods/MethodDescription.java
Normal file
@ -0,0 +1,85 @@
|
||||
package hashmethods;
|
||||
|
||||
import fr.xephi.authme.security.crypts.EncryptionMethod;
|
||||
import fr.xephi.authme.security.crypts.description.SaltType;
|
||||
import fr.xephi.authme.security.crypts.description.Usage;
|
||||
|
||||
/**
|
||||
* Description of a {@link EncryptionMethod}.
|
||||
*/
|
||||
public class MethodDescription {
|
||||
|
||||
/** The implementation class the description belongs to. */
|
||||
private final Class<? extends EncryptionMethod> method;
|
||||
/** The type of the salt that is used. */
|
||||
private SaltType saltType;
|
||||
/** The length of the salt for SaltType.TEXT salts. */
|
||||
private Integer saltLength;
|
||||
/** The usage recommendation. */
|
||||
private Usage usage;
|
||||
/** Whether or not the encryption method is restricted to ASCII characters for proper functioning. */
|
||||
private boolean asciiRestricted;
|
||||
/** Whether or not the encryption method requires its salt stored separately. */
|
||||
private boolean hasSeparateSalt;
|
||||
/** The length of the hash output, based on a test hash (i.e. assumes same length for all hashes.) */
|
||||
private int hashLength;
|
||||
|
||||
public MethodDescription(Class<? extends EncryptionMethod> method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
|
||||
// Trivial getters and setters
|
||||
public Class<? extends EncryptionMethod> getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public SaltType getSaltType() {
|
||||
return saltType;
|
||||
}
|
||||
|
||||
public void setSaltType(SaltType saltType) {
|
||||
this.saltType = saltType;
|
||||
}
|
||||
|
||||
public Integer getSaltLength() {
|
||||
return saltLength;
|
||||
}
|
||||
|
||||
public void setSaltLength(int saltLength) {
|
||||
this.saltLength = saltLength;
|
||||
}
|
||||
|
||||
public Usage getUsage() {
|
||||
return usage;
|
||||
}
|
||||
|
||||
public void setUsage(Usage usage) {
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
public boolean isAsciiRestricted() {
|
||||
return asciiRestricted;
|
||||
}
|
||||
|
||||
public void setAsciiRestricted(boolean asciiRestricted) {
|
||||
this.asciiRestricted = asciiRestricted;
|
||||
}
|
||||
|
||||
public boolean hasSeparateSalt() {
|
||||
return hasSeparateSalt;
|
||||
}
|
||||
|
||||
public void setHasSeparateSalt(boolean hasSeparateSalt) {
|
||||
this.hasSeparateSalt = hasSeparateSalt;
|
||||
}
|
||||
|
||||
public int getHashLength() {
|
||||
return hashLength;
|
||||
}
|
||||
|
||||
public void setHashLength(int hashLength) {
|
||||
this.hashLength = hashLength;
|
||||
}
|
||||
|
||||
}
|
53
src/tools/hashmethods/hash_algorithms.tpl.md
Normal file
53
src/tools/hashmethods/hash_algorithms.tpl.md
Normal file
@ -0,0 +1,53 @@
|
||||
<!-- {gen_warning} -->
|
||||
<!-- File auto-generated on {gen_date}. See hashmethods/hash_algorithms.tpl.md -->
|
||||
|
||||
## Hash Algorithms
|
||||
AuthMe supports the following hash algorithms for storing your passwords safely.
|
||||
|
||||
|
||||
Algorithm | Recommendation | Hash length | ASCII | | Salt type | Length | Separate? |
|
||||
--------- | -------------- | ----------- | ----- | - | --------- | ------ | --------- |
|
||||
{method_rows}CUSTOM | | | | | | | |
|
||||
|
||||
<!-- {gen_warning} -->
|
||||
|
||||
### Columns
|
||||
#### Algorithm
|
||||
The algorithm is the hashing algorithm used to store passwords with. Default is SHA256 and is recommended.
|
||||
You can change the hashing algorithm in the config.yml: under `security`, locate `passwordHash`.
|
||||
|
||||
#### Recommendation
|
||||
The recommendation lists our usage recommendation in terms of how secure it is (not how _well_ the algorithm works!).
|
||||
- Recommended: The hash algorithm appears to be cryptographically secure and is one we recommend.
|
||||
- Acceptable: There are safer algorithms that can be chosen but using the algorithm is generally OK.
|
||||
- Do not use: Hash algorithm isn't sufficiently secure. Use only if required to hook into another system.
|
||||
- Does not work: The algorithm does not work properly; do not use.
|
||||
|
||||
#### Hash Length
|
||||
The length of the hashes the algorithm produces. Note that the hash length is not (primarily) indicative of
|
||||
whether an algorithm is secure or not.
|
||||
|
||||
#### ASCII
|
||||
If denoted with a **y**, means that the algorithm is restricted to ASCII characters only, i.e. it will simply ignore
|
||||
"special characters" such as `ÿ` or `Â`. Note that we do not recommend the use of "special characters" in passwords.
|
||||
|
||||
#### Salt Columns
|
||||
Before hashing, a _salt_ may be appended to the password to make the hash more secure. The following columns describe
|
||||
the salt the algorithm uses.
|
||||
<!-- {gen_warning} -->
|
||||
|
||||
##### Salt Type
|
||||
We do not recommend the usage
|
||||
of any algorithm that doesn't use a randomly generated text as salt. This "salt type" column indicates what type of
|
||||
salt the algorithm uses:
|
||||
- Text: randomly generated text (see also the following column, "Length")
|
||||
- Username: the salt is constructed from the username (bad)
|
||||
- None: the algorithm uses no salt (bad)
|
||||
|
||||
##### Length
|
||||
If applicable (salt type is "Text"), indicates the length of the generated salt. The longer the better.
|
||||
If this column is empty when the salt type is "Text", it typically means the salt length can be defined in config.yml.
|
||||
|
||||
##### Separate
|
||||
If denoted with a **y**, it means that the salt is stored in a separate column in the database. This is neither good
|
||||
or bad.
|
1
src/tools/hashmethods/hash_algorithms_row.tpl.md
Normal file
1
src/tools/hashmethods/hash_algorithms_row.tpl.md
Normal file
@ -0,0 +1 @@
|
||||
{name} | {recommendation} | {hash_length} | {ascii_restricted} | | {salt_type} | {salt_length} | {separate_salt}
|
Loading…
Reference in New Issue
Block a user