Initial commit.
This commit is contained in:
commit
11a3456c53
30
.gitignore
vendored
Normal file
30
.gitignore
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
# Built files
|
||||
out/
|
||||
|
||||
### NetBeans ###
|
||||
nbproject/private/
|
||||
build/
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
.nb-gradle/
|
8
.idea/.gitignore
vendored
Normal file
8
.idea/.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
7
.idea/discord.xml
Normal file
7
.idea/discord.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
<option name="description" value="" />
|
||||
</component>
|
||||
</project>
|
6
.idea/misc.xml
Normal file
6
.idea/misc.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/calmstdcrypt.iml" filepath="$PROJECT_DIR$/calmstdcrypt.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
10
.idea/runConfigurations.xml
Normal file
10
.idea/runConfigurations.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
29
LICENSE
Normal file
29
LICENSE
Normal file
@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2022, Captain ALM
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
7
README.md
Normal file
7
README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Captain ALM Standard Crypto Library (Java)
|
||||
|
||||
This is my standard cryptographic library that wraps the java cryptographic functions.
|
||||
|
||||
This application targets Java 8.
|
||||
|
||||
(C) Captain ALM 2022 - Under the BSD 3-Clause License
|
11
calmstdcrypt.iml
Normal file
11
calmstdcrypt.iml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
42
src/com/captainalm/lib/stdcrypt/digest/DigestComparer.java
Normal file
42
src/com/captainalm/lib/stdcrypt/digest/DigestComparer.java
Normal file
@ -0,0 +1,42 @@
|
||||
package com.captainalm.lib.stdcrypt.digest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* This class provides the ability to compare digests.
|
||||
*
|
||||
* @author Captain ALM
|
||||
*/
|
||||
public class DigestComparer {
|
||||
/**
|
||||
* Compares two digests.
|
||||
*
|
||||
* @param digest1 The first digest array.
|
||||
* @param digest2 The second digest array.
|
||||
* @return If the digests are equivalent.
|
||||
*/
|
||||
public static boolean compareDigests(byte[] digest1, byte[] digest2) {
|
||||
if ((digest1 == null && digest2 != null) || (digest1 != null && digest2 == null)) return false;
|
||||
if (digest1 == digest2) return true;
|
||||
if (digest1.length != digest2.length) return false;
|
||||
for (int i = 0; i < digest1.length; i++) if (digest1[i] != digest2[i]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares a digest from an {@link InputStream} with a digest array.
|
||||
*
|
||||
* @param digest1Stream The input stream digest.
|
||||
* @param digest2 The digest array.
|
||||
* @return If the digests are equivalent.
|
||||
* @throws IOException An I/O Exception has occurred.
|
||||
*/
|
||||
public static boolean compareDigests(InputStream digest1Stream, byte[] digest2) throws IOException {
|
||||
if (digest1Stream == null || digest2 == null) return false;
|
||||
if (digest2.length == 0) return false;
|
||||
int c;
|
||||
for (byte b : digest2) if ((c = digest1Stream.read()) == -1 || (byte) c != b) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
190
src/com/captainalm/lib/stdcrypt/digest/DigestProvider.java
Normal file
190
src/com/captainalm/lib/stdcrypt/digest/DigestProvider.java
Normal file
@ -0,0 +1,190 @@
|
||||
package com.captainalm.lib.stdcrypt.digest;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
/**
|
||||
* This class allows for obtaining {@link DigestInputStream} and {@link DigestOutputStream} using the specified algorithm.
|
||||
*
|
||||
* @author Captain ALM
|
||||
*/
|
||||
public final class DigestProvider implements Cloneable {
|
||||
private MessageDigest digest;
|
||||
private boolean shouldClone;
|
||||
|
||||
/**
|
||||
* Constructs a new digest provider with the specified algorithm.
|
||||
*
|
||||
* @param algorithm The algorithm of the digest.
|
||||
* @throws NullPointerException algorithm is null.
|
||||
* @throws NoSuchAlgorithmException The algorithm does not exist.
|
||||
*/
|
||||
public DigestProvider(String algorithm) throws NoSuchAlgorithmException {
|
||||
this(algorithm, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new digest provider with the specified algorithm
|
||||
* and if the digest should be cloned for created streams.
|
||||
*
|
||||
* @param algorithm The algorithm of the digest.
|
||||
* @param shouldClone The digest should be cloned when creating streams.
|
||||
* @throws NullPointerException algorithm is null.
|
||||
* @throws NoSuchAlgorithmException The algorithm does not exist.
|
||||
*/
|
||||
public DigestProvider(String algorithm, boolean shouldClone) throws NoSuchAlgorithmException {
|
||||
if (algorithm == null) throw new NullPointerException("algorithm is null");
|
||||
digest = MessageDigest.getInstance(algorithm);
|
||||
this.shouldClone = shouldClone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the digest input stream for this class.
|
||||
* NOTE: If using any other streams on this digest, and {@link #digestClonedForStreams()} is false,
|
||||
* The current calculated digest for this stream changes for all the other streams.
|
||||
*
|
||||
* @param inputStream The input stream to get the digest for.
|
||||
* @return The digest input stream.
|
||||
*/
|
||||
public DigestInputStream getDigestInputStream(InputStream inputStream) {
|
||||
if (inputStream == null) throw new NullPointerException("inputStream is null");
|
||||
digest.reset();
|
||||
try {
|
||||
return new DigestInputStream(inputStream, (shouldClone) ? (MessageDigest) digest.clone() : digest);
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return new DigestInputStream(inputStream, digest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the digest output stream for this class.
|
||||
* NOTE: If using any other streams on this digest, and {@link #digestClonedForStreams()} is false,
|
||||
* The current calculated digest for this stream changes for all the other streams.
|
||||
*
|
||||
* @param outputStream The output stream to get the digest for.
|
||||
* @return The digest output stream.
|
||||
*/
|
||||
public DigestOutputStream getDigestOutputStream(OutputStream outputStream) {
|
||||
if (outputStream == null) throw new NullPointerException("outputStream is null");
|
||||
digest.reset();
|
||||
try {
|
||||
return new DigestOutputStream(outputStream, (shouldClone) ? (MessageDigest) digest.clone() : digest);
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return new DigestOutputStream(outputStream, digest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the algorithm of this provider.
|
||||
*
|
||||
* @return The algorithm.
|
||||
*/
|
||||
public String getAlgorithm() {
|
||||
return digest.getAlgorithm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of the algorithm in bytes.
|
||||
*
|
||||
* @return The length in bytes.
|
||||
*/
|
||||
public int getLength() {
|
||||
return digest.getDigestLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether {@link MessageDigest}s are cloned for streams.
|
||||
*
|
||||
* @return If the digests are cloned.
|
||||
*/
|
||||
public boolean digestClonedForStreams() {
|
||||
return shouldClone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the digest of the specified array.
|
||||
* NOTE: If using any streams on this digest, and {@link #digestClonedForStreams()} is false,
|
||||
* The current calculated digest for all these streams are reset.
|
||||
*
|
||||
* @param dataIn The byte array to find the digest of.
|
||||
* @return The digest array.
|
||||
*/
|
||||
public byte[] getDigestOf(byte[] dataIn) {
|
||||
digest.reset();
|
||||
return digest.digest(dataIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this object.
|
||||
*
|
||||
* @return The clone of this object.
|
||||
*/
|
||||
@Override
|
||||
public Object clone() {
|
||||
try {
|
||||
return new DigestProvider(digest.getAlgorithm(), shouldClone);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance for MD5.
|
||||
*
|
||||
* @param shouldClone The digest should be cloned when creating streams.
|
||||
* @return The DigestProvider for MD5 or null.
|
||||
*/
|
||||
public static DigestProvider getMD5Instance(boolean shouldClone) {
|
||||
try {
|
||||
return new DigestProvider("MD5", shouldClone);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance for SHA-1.
|
||||
*
|
||||
* @param shouldClone The digest should be cloned when creating streams.
|
||||
* @return The DigestProvider for SHA-1 or null.
|
||||
*/
|
||||
public static DigestProvider getSHA1Instance(boolean shouldClone) {
|
||||
try {
|
||||
return new DigestProvider("SHA-1", shouldClone);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance for SHA-256.
|
||||
*
|
||||
* @param shouldClone The digest should be cloned when creating streams.
|
||||
* @return The DigestProvider for SHA-256 or null.
|
||||
*/
|
||||
public static DigestProvider getSHA256Instance(boolean shouldClone) {
|
||||
try {
|
||||
return new DigestProvider("SHA-256", shouldClone);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instance for SHA-512.
|
||||
*
|
||||
* @param shouldClone The digest should be cloned when creating streams.
|
||||
* @return The DigestProvider for SHA-512 or null.
|
||||
*/
|
||||
public static DigestProvider getSHA512Instance(boolean shouldClone) {
|
||||
try {
|
||||
return new DigestProvider("SHA-512", shouldClone);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
6
src/com/captainalm/lib/stdcrypt/digest/package-info.java
Normal file
6
src/com/captainalm/lib/stdcrypt/digest/package-info.java
Normal file
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* This package contains the digest objects.
|
||||
*
|
||||
* @author Captain ALM
|
||||
*/
|
||||
package com.captainalm.lib.stdcrypt.digest;
|
@ -0,0 +1,367 @@
|
||||
package com.captainalm.lib.stdcrypt.encryption;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
||||
/**
|
||||
* This class provides an AES cipher that uses Rfc2898 for key generation and a string password.
|
||||
*
|
||||
* @author Captain ALM
|
||||
*/
|
||||
public class AESPasswordRfc2898CipherFactory implements ICipherFactory {
|
||||
protected static final int iVectorDefaultSize = 16;
|
||||
protected static final int saltDefaultSize = 32;
|
||||
protected static final int iterations = 2000;
|
||||
protected static final int keySize = 256;
|
||||
|
||||
protected final Object slock = new Object();
|
||||
|
||||
protected String password; //Cannot be exported in settings
|
||||
protected byte[] salt;
|
||||
protected byte[] iVector;
|
||||
protected byte[] passwordCache;
|
||||
|
||||
protected boolean outputSalt;
|
||||
protected boolean outputIVector;
|
||||
|
||||
protected boolean haveAttributesChanged;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of AESPasswordRfc2898CipherFactory with the specified password.
|
||||
*
|
||||
* @param password The password to use.
|
||||
* @throws NullPointerException password is null.
|
||||
*/
|
||||
public AESPasswordRfc2898CipherFactory(String password) {
|
||||
this(password, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of AESPasswordRfc2898CipherFactory with the specified password, salt and initialization vector.
|
||||
*
|
||||
* @param password The password to use.
|
||||
* @param salt The salt to use or null.
|
||||
* @param initializationVector The initialization vector to use or null.
|
||||
* @throws NullPointerException password is null.
|
||||
* @throws IllegalArgumentException salt or initializationVector is larger than 255.
|
||||
*/
|
||||
public AESPasswordRfc2898CipherFactory(String password, byte[] salt, byte[] initializationVector) {
|
||||
setPassword(password);
|
||||
setSalt(salt);
|
||||
setInitializationVector(initializationVector);
|
||||
haveAttributesChanged = false;
|
||||
}
|
||||
|
||||
protected void processPasswordCache() {
|
||||
if (passwordCache == null) passwordCache = password.getBytes(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a new cipher instance.
|
||||
*
|
||||
* @param opmode The Cipher Operation Mode ({@link Cipher#ENCRYPT_MODE}, {@link Cipher#DECRYPT_MODE}, {@link Cipher#WRAP_MODE} and {@link Cipher#UNWRAP_MODE}).
|
||||
* @return The new cipher instance or null.
|
||||
* @throws CipherException An Exception has occurred.
|
||||
*/
|
||||
@Override
|
||||
public Cipher getCipher(int opmode) throws CipherException {
|
||||
try {
|
||||
if (salt == null || salt.length < 1) {
|
||||
salt = new byte[saltDefaultSize];
|
||||
SecureRandom.getInstanceStrong().nextBytes(salt);
|
||||
}
|
||||
|
||||
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), salt, iterations, keySize);
|
||||
SecretKeySpec secretSpec = new SecretKeySpec(keyFactory.generateSecret(pbeKeySpec).getEncoded(), "AES");
|
||||
|
||||
if (iVector == null || iVector.length < 1) {
|
||||
iVector = new byte[iVectorDefaultSize];
|
||||
SecureRandom.getInstanceStrong().nextBytes(iVector);
|
||||
}
|
||||
AlgorithmParameterSpec ivSpec = new IvParameterSpec(iVector);
|
||||
|
||||
Cipher toret = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
toret.init(opmode, secretSpec, ivSpec);
|
||||
return toret;
|
||||
} catch (NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | InvalidAlgorithmParameterException e) {
|
||||
throw new CipherException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the cipher factory.
|
||||
*
|
||||
* @return The name of the cipher factory.
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return "AES Password Rfc 2898";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets if the cipher settings attributes have been modified.
|
||||
* Resets the flag once checked.
|
||||
*
|
||||
* @return If the attributes have been modified.
|
||||
*/
|
||||
@Override
|
||||
public boolean cipherAttributesModified() {
|
||||
synchronized (slock) {
|
||||
boolean toret = haveAttributesChanged;
|
||||
haveAttributesChanged = false;
|
||||
return toret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cipher settings as a byte array.
|
||||
*
|
||||
* @return The byte array of the settings.
|
||||
*/
|
||||
@Override
|
||||
public byte[] getSettings() {
|
||||
synchronized (slock) {
|
||||
processPasswordCache();
|
||||
byte[] toret = new byte[1 + ((passwordCache == null) ? 0 : passwordCache.length + 4) + ((salt == null) ? 0 : salt.length + 1) + ((iVector == null) ? 0 : iVector.length + 1)];
|
||||
toret[0] = (byte) (((passwordCache == null) ? 0 : 1) + ((salt == null) ? 0 : 2) + ((iVector == null) ? 0 : 4));
|
||||
|
||||
int index = 1;
|
||||
if (passwordCache != null) {
|
||||
int length = passwordCache.length;
|
||||
|
||||
toret[index++] = (byte) (length / 16777216);
|
||||
length %= 16777216;
|
||||
toret[index++] = (byte) (length / 65536);
|
||||
length %= 65536;
|
||||
toret[index++] = (byte) (length / 256);
|
||||
length %= 256;
|
||||
toret[index++] = (byte) (length);
|
||||
|
||||
System.arraycopy(passwordCache, 0, toret, index, passwordCache.length); index += passwordCache.length;
|
||||
}
|
||||
|
||||
if (salt != null) {
|
||||
toret[index++] = (byte) salt.length;
|
||||
System.arraycopy(salt, 0, toret, index, salt.length); index += salt.length;
|
||||
}
|
||||
|
||||
if (iVector != null) {
|
||||
toret[index++] = (byte) iVector.length;
|
||||
System.arraycopy(iVector, 0, toret, index, iVector.length);
|
||||
}
|
||||
|
||||
return toret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of the settings byte array.
|
||||
*
|
||||
* @return The length of the settings byte array.
|
||||
*/
|
||||
@Override
|
||||
public int getSettingsLength() {
|
||||
synchronized (slock) {
|
||||
processPasswordCache();
|
||||
return 1 + ((passwordCache == null) ? 0 : passwordCache.length + 4) + ((salt == null) ? 0 : salt.length + 1) + ((iVector == null) ? 0 : iVector.length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cipher settings as a byte array without secrets.
|
||||
*
|
||||
* @return The byte array of the settings without secrets.
|
||||
*/
|
||||
@Override
|
||||
public byte[] getSettingsNoSecrets() {
|
||||
synchronized (slock) {
|
||||
byte[] toret = new byte[1 + ((salt == null) ? 0 : salt.length + 1) + ((iVector == null) ? 0 : iVector.length + 1)];
|
||||
toret[0] = (byte) (((salt == null) ? 0 : 2) + ((iVector == null) ? 0 : 4));
|
||||
|
||||
int index = 1;
|
||||
if (salt != null) {
|
||||
toret[index++] = (byte) salt.length;
|
||||
System.arraycopy(salt, 0, toret, index, salt.length); index += salt.length;
|
||||
}
|
||||
|
||||
if (iVector != null) {
|
||||
toret[index++] = (byte) iVector.length;
|
||||
System.arraycopy(iVector, 0, toret, index, iVector.length);
|
||||
}
|
||||
|
||||
return toret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the length of the settings byte array without secrets.
|
||||
*
|
||||
* @return The length of the settings byte array without secrets.
|
||||
*/
|
||||
@Override
|
||||
public int getSettingsNoSecretsLength() {
|
||||
synchronized (slock) {
|
||||
return 1 + ((salt == null) ? 0 : salt.length + 1) + ((iVector == null) ? 0 : iVector.length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cipher settings using a byte array.
|
||||
*
|
||||
* @param settingsIn The byte array to load the settings from.
|
||||
* @throws NullPointerException settingsIn is null.
|
||||
* @throws CipherException An Exception has occurred.
|
||||
*/
|
||||
@Override
|
||||
public void setSettings(byte[] settingsIn) throws CipherException {
|
||||
if (settingsIn == null) throw new NullPointerException("settingsIn is null");
|
||||
if (settingsIn.length < 1) throw new CipherException("no data");
|
||||
synchronized (slock) {
|
||||
int index = 1;
|
||||
if (((settingsIn[0] & 4) == 4)) {
|
||||
int pwdLength = (settingsIn[index++] & 0xff) * 16777216;
|
||||
pwdLength += (settingsIn[index++] & 0xff) * 65536;
|
||||
pwdLength += (settingsIn[index++] & 0xff) * 256;
|
||||
pwdLength += (settingsIn[index++] & 0xff);
|
||||
if (pwdLength < 1) throw new CipherException("password length less than 1");
|
||||
|
||||
passwordCache = new byte[pwdLength];
|
||||
System.arraycopy(settingsIn, index, passwordCache, 0, pwdLength); index += pwdLength;
|
||||
|
||||
password = new String(passwordCache, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
if (((settingsIn[0] & 8) == 8)) {
|
||||
int length = settingsIn[index++] & 0xff;
|
||||
if (length < 1) throw new CipherException("salt length less than 1");
|
||||
salt = new byte[length];
|
||||
System.arraycopy(settingsIn, index, salt, 0, length); index += length;
|
||||
}
|
||||
|
||||
if (((settingsIn[0] & 16) == 16)) {
|
||||
int length = settingsIn[index++] & 0xff;
|
||||
if (length < 1) throw new CipherException("initializationVector length less than 1");
|
||||
iVector = new byte[length];
|
||||
System.arraycopy(settingsIn, index, iVector, 0, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the password.
|
||||
*
|
||||
* @return The password.
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the password.
|
||||
*
|
||||
* @param password The new password.
|
||||
* @throws NullPointerException password is null.
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
if (password == null) throw new NullPointerException("password is null");
|
||||
synchronized (slock) {
|
||||
haveAttributesChanged = true;
|
||||
this.password = password;
|
||||
passwordCache = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the salt in use.
|
||||
*
|
||||
* @return The salt.
|
||||
*/
|
||||
public byte[] getSalt() {
|
||||
return salt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the salt in use, set to null to generate a random salt.
|
||||
*
|
||||
* @param salt The new salt or null.
|
||||
* @throws IllegalArgumentException salt is larger than 255.
|
||||
*/
|
||||
public void setSalt(byte[] salt) {
|
||||
if (salt != null && salt.length > 255) throw new IllegalArgumentException("salt is larger than 255");
|
||||
synchronized (slock) {
|
||||
haveAttributesChanged = true;
|
||||
this.salt = salt;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the initialization vector.
|
||||
*
|
||||
* @return The initialization vector.
|
||||
*/
|
||||
public byte[] getInitializationVector() {
|
||||
return iVector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the initialization vector in use, set to null to generate a random initialization vector.
|
||||
*
|
||||
* @param initializationVector The new initialization vector or null.
|
||||
* @throws IllegalArgumentException initializationVector is larger than 255.
|
||||
*/
|
||||
public void setInitializationVector(byte[] initializationVector) {
|
||||
if (initializationVector != null && initializationVector.length > 255) throw new IllegalArgumentException("initializationVector is larger than 255");
|
||||
synchronized (slock) {
|
||||
haveAttributesChanged = true;
|
||||
iVector = initializationVector;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the salt is output.
|
||||
*
|
||||
* @return Is the salt output.
|
||||
*/
|
||||
public boolean isOutputtingSalt() {
|
||||
return outputSalt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the salt is output.
|
||||
*
|
||||
* @param outputSalt Should the salt be output.
|
||||
*/
|
||||
public void setOutputSalt(boolean outputSalt) {
|
||||
this.outputSalt = outputSalt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the InitializationVector is output.
|
||||
*
|
||||
* @return Is the InitializationVector output.
|
||||
*/
|
||||
public boolean isOutputtingInitializationVector() {
|
||||
return outputIVector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if the InitializationVector is output.
|
||||
*
|
||||
* @param outputInitializationVector Should the InitializationVector be output.
|
||||
*/
|
||||
public void setOutputInitializationVector(boolean outputInitializationVector) {
|
||||
outputIVector = outputInitializationVector;
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.captainalm.lib.stdcrypt.encryption;
|
||||
|
||||
import java.security.PrivilegedActionException;
|
||||
|
||||
/**
|
||||
* This class provides the cipher exception wrapper class.
|
||||
* See {@link CipherException#getCause()} to find out the underlying exception.
|
||||
*
|
||||
* @author Captain ALM
|
||||
*/
|
||||
public class CipherException extends Exception {
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message. The
|
||||
* cause is not initialized, and may subsequently be initialized by
|
||||
* a call to {@link #initCause}.
|
||||
*
|
||||
* @param message the detail message. The detail message is saved for
|
||||
* later retrieval by the {@link #getMessage()} method.
|
||||
*/
|
||||
public CipherException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified detail message and
|
||||
* cause. <p>Note that the detail message associated with
|
||||
* {@code cause} is <i>not</i> automatically incorporated in
|
||||
* this exception's detail message.
|
||||
*
|
||||
* @param message the detail message (which is saved for later retrieval
|
||||
* by the {@link #getMessage()} method).
|
||||
* @param cause the cause (which is saved for later retrieval by the
|
||||
* {@link #getCause()} method). (A <tt>null</tt> value is
|
||||
* permitted, and indicates that the cause is nonexistent or
|
||||
* unknown.)
|
||||
* @since 1.4
|
||||
*/
|
||||
public CipherException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new exception with the specified cause and a detail
|
||||
* message of <tt>(cause==null ? null : cause.toString())</tt> (which
|
||||
* typically contains the class and detail message of <tt>cause</tt>).
|
||||
* This constructor is useful for exceptions that are little more than
|
||||
* wrappers for other throwables (for example, {@link
|
||||
* PrivilegedActionException}).
|
||||
*
|
||||
* @param cause the cause (which is saved for later retrieval by the
|
||||
* {@link #getCause()} method). (A <tt>null</tt> value is
|
||||
* permitted, and indicates that the cause is nonexistent or
|
||||
* unknown.)
|
||||
* @since 1.4
|
||||
*/
|
||||
public CipherException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package com.captainalm.lib.stdcrypt.encryption;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
/**
|
||||
* This interface provides the ability to obtain a {@link Cipher} and get and set its settings.
|
||||
*
|
||||
* @author Captain ALM
|
||||
*/
|
||||
public interface ICipherFactory {
|
||||
/**
|
||||
* Gets a new cipher instance.
|
||||
*
|
||||
* @param opmode The Cipher Operation Mode ({@link Cipher#ENCRYPT_MODE}, {@link Cipher#DECRYPT_MODE}, {@link Cipher#WRAP_MODE} and {@link Cipher#UNWRAP_MODE}).
|
||||
* @return The new cipher instance or null.
|
||||
* @throws CipherException An Exception has occurred.
|
||||
*/
|
||||
Cipher getCipher(int opmode) throws CipherException;
|
||||
|
||||
/**
|
||||
* Gets the name of the cipher factory.
|
||||
*
|
||||
* @return The name of the cipher factory.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets if the cipher settings attributes have been modified.
|
||||
* Resets the flag once checked.
|
||||
*
|
||||
* @return If the attributes have been modified.
|
||||
*/
|
||||
boolean cipherAttributesModified();
|
||||
|
||||
/**
|
||||
* Gets the cipher settings as a byte array.
|
||||
*
|
||||
* @return The byte array of the settings.
|
||||
*/
|
||||
byte[] getSettings();
|
||||
|
||||
/**
|
||||
* Gets the length of the settings byte array.
|
||||
*
|
||||
* @return The length of the settings byte array.
|
||||
*/
|
||||
int getSettingsLength();
|
||||
|
||||
/**
|
||||
* Gets the cipher settings as a byte array without secrets.
|
||||
*
|
||||
* @return The byte array of the settings without secrets.
|
||||
*/
|
||||
byte[] getSettingsNoSecrets();
|
||||
|
||||
/**
|
||||
* Gets the length of the settings byte array without secrets.
|
||||
*
|
||||
* @return The length of the settings byte array without secrets.
|
||||
*/
|
||||
int getSettingsNoSecretsLength();
|
||||
|
||||
/**
|
||||
* Sets the cipher settings using a byte array.
|
||||
*
|
||||
* @param settingsIn The byte array to load the settings from.
|
||||
* @throws NullPointerException settingsIn is null.
|
||||
* @throws CipherException An Exception has occurred.
|
||||
*/
|
||||
void setSettings(byte[] settingsIn) throws CipherException;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* This package contains the encryption objects.
|
||||
*
|
||||
* @author Captain ALM
|
||||
*/
|
||||
package com.captainalm.lib.stdcrypt.encryption;
|
8
src/com/captainalm/lib/stdcrypt/package-info.java
Normal file
8
src/com/captainalm/lib/stdcrypt/package-info.java
Normal file
@ -0,0 +1,8 @@
|
||||
/**
|
||||
* This library contains the standard {@link com.captainalm.lib.stdcrypt.digest} and {@link com.captainalm.lib.stdcrypt.encryption} logic.
|
||||
*
|
||||
* @since 0.0
|
||||
* @author Captain ALM
|
||||
* @version 0.0
|
||||
*/
|
||||
package com.captainalm.lib.stdcrypt;
|
Loading…
Reference in New Issue
Block a user