Skip to content

Commit

Permalink
Merge branch 'release/v1.6.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
John-Chan committed Sep 16, 2024
2 parents 2bc2073 + 37d70f2 commit 65d5b40
Show file tree
Hide file tree
Showing 31 changed files with 791 additions and 241 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

<properties>
<skipTests>false</skipTests>
<revision>1.6.1</revision>
<revision>1.6.2</revision>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@

package com.power4j.tile.crypto.bc;

import com.power4j.tile.crypto.core.BlockCipher;
import com.power4j.tile.crypto.core.CipherBlob;
import com.power4j.tile.crypto.core.CipherBlobEnvelope;
import com.power4j.tile.crypto.core.CipherBlobDetails;
import com.power4j.tile.crypto.core.GeneralCryptoException;
import com.power4j.tile.crypto.core.QuickCipher;
import com.power4j.tile.crypto.core.Slice;
import com.power4j.tile.crypto.core.UncheckedCipher;
import com.power4j.tile.crypto.core.Verified;
import com.power4j.tile.crypto.utils.CryptoUtil;
import org.springframework.lang.Nullable;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
Expand All @@ -35,9 +37,9 @@
* @author CJ ([email protected])
* @since 1.6
*/
public class BouncyCastleBlockCipher implements BlockCipher {
public class BouncyCastleQuickCipher implements QuickCipher {

private final String transformation;
private final Cipher cipher;

private final Supplier<SecretKeySpec> keySupplier;

Expand All @@ -47,12 +49,13 @@ public class BouncyCastleBlockCipher implements BlockCipher {

private final Function<byte[], byte[]> checksumCalculator;

private final BiFunction<CipherBlob, byte[], Boolean> checksumVerifier;
private final BiFunction<UncheckedCipher, byte[], Boolean> checksumVerifier;

public BouncyCastleBlockCipher(String transformation, Supplier<SecretKeySpec> keySupplier,
public BouncyCastleQuickCipher(String transformation, Supplier<SecretKeySpec> keySupplier,
Supplier<IvParameterSpec> ivParameterSpecSupplier, Function<byte[], byte[]> checksumCalculator,
BiFunction<CipherBlob, byte[], Boolean> checksumVerifier) {
this.transformation = transformation;
BiFunction<UncheckedCipher, byte[], Boolean> checksumVerifier) {
this.cipher = CryptoUtil.createCipher(transformation);
;
this.keySupplier = keySupplier;
this.ivParameterSpecSupplier = ivParameterSpecSupplier;
this.checksumCalculator = checksumCalculator;
Expand All @@ -61,21 +64,19 @@ public BouncyCastleBlockCipher(String transformation, Supplier<SecretKeySpec> ke
}

@Override
public CipherBlobEnvelope encryptEnvelope(byte[] data) throws GeneralCryptoException {
public CipherBlobDetails encrypt(byte[] data, int offset, int length) throws GeneralCryptoException {
final IvParameterSpec ivParameter = ivParameterSpecSupplier.get();
byte[] encrypted;
byte[] checksum;
try {
checksum = checksumCalculator.apply(data);
Cipher cipher = CryptoUtil.createCipher(transformation);
cipher.init(Cipher.ENCRYPT_MODE, keySupplier.get(), ivParameter);
encrypted = cipher.doFinal(data);
encrypted = oneStep(Cipher.ENCRYPT_MODE, keySupplier.get(), ivParameter, Slice.wrap(data));
}
catch (GeneralSecurityException e) {
throw new GeneralCryptoException(e.getMessage(), e);
catch (Exception e) {
throw CryptoUtil.wrapGeneralCryptoException(null, e);
}
byte[] ivBytes = ivParameter == null ? null : ivParameter.getIV();
return CipherBlobEnvelope.builder()
return CipherBlobDetails.builder()
.algorithm(transformationParts[0])
.mode(transformationParts[1])
.padding(transformationParts[2])
Expand All @@ -86,21 +87,26 @@ public CipherBlobEnvelope encryptEnvelope(byte[] data) throws GeneralCryptoExcep
}

@Override
public Verified<byte[]> decrypt(CipherBlob store, boolean skipCheck) throws GeneralCryptoException {
public Verified<byte[]> decrypt(UncheckedCipher input, boolean skipCheck) throws GeneralCryptoException {
byte[] decrypted;
try {
Cipher cipher = CryptoUtil.createCipher(transformation);
cipher.init(Cipher.DECRYPT_MODE, keySupplier.get(), ivParameterSpecSupplier.get());
decrypted = cipher.doFinal(store.getCipher());
decrypted = oneStep(Cipher.DECRYPT_MODE, keySupplier.get(), ivParameterSpecSupplier.get(),
input.getCipher());
}
catch (GeneralSecurityException e) {
return Verified.fail(null, e);
}
if (skipCheck) {
return Verified.pass(decrypted);
}
return checksumVerifier.apply(store, decrypted) ? Verified.pass(decrypted) : Verified.fail(decrypted, null);
return checksumVerifier.apply(input, decrypted) ? Verified.pass(decrypted) : Verified.fail(decrypted, null);

}

protected final synchronized byte[] oneStep(int mode, SecretKeySpec key, @Nullable IvParameterSpec iv, Slice data)
throws GeneralSecurityException {
cipher.init(mode, key, iv);
return cipher.doFinal(data.getData(), data.getOffset(), data.getLength());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
*/
@Getter
@Builder
public class CipherBlobEnvelope {
public class CipherBlobDetails {

private final String algorithm;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
*/
@Getter
@Builder
public class CiphertextEnvelope {
public class CiphertextDetails {

private final String encoding;

Expand Down Expand Up @@ -57,7 +57,7 @@ public Optional<String> getIvOptional(boolean trimToNull) {

@Override
public String toString() {
return "CiphertextEnvelope{" + "encoding='" + encoding + '\'' + ", algorithm='" + algorithm + '\''
return "CiphertextDetails{" + "encoding='" + encoding + '\'' + ", algorithm='" + algorithm + '\''
+ ", padding='" + padding + '\'' + ", mode='" + mode + '\'' + ", iv='" + iv + '\'' + ", ciphertext='"
+ ciphertext + '\'' + ", checksum='" + checksum + '\'' + '}';
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,10 @@

package com.power4j.tile.crypto.core;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

/**
* @author CJ ([email protected])
* @since 1.0
*/
@Getter
@RequiredArgsConstructor
public class CipherBlob {

private final byte[] cipher;

private final byte[] checksum;
public interface QuickCipher extends QuickEnc, QuickDec {

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package com.power4j.tile.crypto.core;

import com.power4j.tile.crypto.bc.BouncyCastleBlockCipher;
import com.power4j.tile.crypto.bc.BouncyCastleQuickCipher;
import com.power4j.tile.crypto.bc.Spec;
import com.power4j.tile.crypto.utils.CryptoUtil;
import com.power4j.tile.crypto.utils.Validate;
Expand All @@ -29,7 +29,7 @@
import java.util.function.Supplier;

/**
* {@link BlockCipher} Builder<br/>
* {@link QuickCipher} Builder<br/>
* <ul>
* <li>algorithmName: 密码算法的名称,如 AES,SM4</li>
* <li>mode: 加密模式,如 ECB, CBC</li>
Expand All @@ -45,7 +45,7 @@
* @see Spec
* @see TextCipherBuilder
*/
public class BlockCipherBuilder {
public class QuickCipherBuilder {

private final String algorithmName;

Expand All @@ -59,103 +59,103 @@ public class BlockCipherBuilder {

private Function<byte[], byte[]> checksumCalculator;

private BiFunction<CipherBlob, byte[], Boolean> checksumVerifier;
private BiFunction<UncheckedCipher, byte[], Boolean> checksumVerifier;

BlockCipherBuilder(String algorithmName) {
QuickCipherBuilder(String algorithmName) {
this.algorithmName = algorithmName;
};

public static BlockCipherBuilder algorithm(String algorithmName) {
return new BlockCipherBuilder(algorithmName);
public static QuickCipherBuilder algorithm(String algorithmName) {
return new QuickCipherBuilder(algorithmName);
}

public BlockCipherBuilder mode(String mode) {
public QuickCipherBuilder mode(String mode) {
this.mode = mode;
return this;
}

public BlockCipherBuilder padding(String padding) {
public QuickCipherBuilder padding(String padding) {
this.padding = padding;
return this;
}

public BlockCipherBuilder secretKeySpecSupplier(Supplier<SecretKeySpec> supplier) {
public QuickCipherBuilder secretKeySpecSupplier(Supplier<SecretKeySpec> supplier) {
this.secretKeySpecSupplier = supplier;
return this;
}

public BlockCipherBuilder secretKey(byte[] key) {
public QuickCipherBuilder secretKey(byte[] key) {
return secretKeySpecSupplier(() -> CryptoUtil.createKey(key, algorithmName));
}

public BlockCipherBuilder secretKeyHex(String val) {
public QuickCipherBuilder secretKeyHex(String val) {
this.secretKeySpecSupplier = () -> CryptoUtil.createKey(CryptoUtil.decodeHex(val, null), algorithmName);
return this;
}

public BlockCipherBuilder secretKeyBase64(String val) {
public QuickCipherBuilder secretKeyBase64(String val) {
this.secretKeySpecSupplier = () -> CryptoUtil.createKey(CryptoUtil.decodeBase64(val, null), algorithmName);
return this;
}

public BlockCipherBuilder ivParameterSpecSupplier(Supplier<IvParameterSpec> supplier) {
public QuickCipherBuilder ivParameterSpecSupplier(Supplier<IvParameterSpec> supplier) {
this.ivParameterSpecSupplier = supplier;
return this;
}

public BlockCipherBuilder ivParameter(@Nullable byte[] iv) {
public QuickCipherBuilder ivParameter(@Nullable byte[] iv) {
if (iv == null) {
return ivParameterSpecSupplier(() -> null);
}
return ivParameterSpecSupplier(() -> new IvParameterSpec(iv));
}

public BlockCipherBuilder ivParameterHex(@Nullable String val) {
public QuickCipherBuilder ivParameterHex(@Nullable String val) {
if (val == null) {
return ivParameterSpecSupplier(() -> null);
}
return ivParameterSpecSupplier(() -> new IvParameterSpec(CryptoUtil.decodeHex(val, null)));
}

public BlockCipherBuilder ivParameterBase64(String val) {
public QuickCipherBuilder ivParameterBase64(String val) {
this.ivParameterSpecSupplier = () -> new IvParameterSpec(CryptoUtil.decodeBase64(val, null));
return this;
}

public BlockCipherBuilder checksumCalculator(@Nullable Function<byte[], byte[]> calculator) {
public QuickCipherBuilder checksumCalculator(@Nullable Function<byte[], byte[]> calculator) {
this.checksumCalculator = calculator;
return this;
}

public BlockCipherBuilder sm3ChecksumCalculator() {
public QuickCipherBuilder sm3ChecksumCalculator() {
this.checksumCalculator = CryptoUtil.SM3_CHECKSUM_CALCULATOR;
return this;
}

public BlockCipherBuilder checksumVerifier(BiFunction<CipherBlob, byte[], Boolean> verifier) {
public QuickCipherBuilder checksumVerifier(BiFunction<UncheckedCipher, byte[], Boolean> verifier) {
this.checksumVerifier = verifier;
return this;
}

public BlockCipherBuilder sm3ChecksumVerifier() {
public QuickCipherBuilder sm3ChecksumVerifier() {
this.checksumVerifier = CryptoUtil.SM3_CHECKSUM_VERIFIER;
return this;
}

public BouncyCastleBlockCipher build() {
public BouncyCastleQuickCipher build() {
Validate.notEmpty(algorithmName, "algorithmName must not be empty");
Validate.notEmpty(mode, "mode must not be empty");
Validate.notEmpty(padding, "padding must not be empty");
Validate.notNull(secretKeySpecSupplier, "secretKeySpecSupplier must not be null");

Function<byte[], byte[]> calculator = checksumCalculator == null ? CryptoUtil.EMPTY_CHECKSUM_CALCULATOR
: checksumCalculator;
BiFunction<CipherBlob, byte[], Boolean> verifier = checksumVerifier == null
BiFunction<UncheckedCipher, byte[], Boolean> verifier = checksumVerifier == null
? CryptoUtil.IGNORED_CHECKSUM_VERIFIER : checksumVerifier;
Supplier<IvParameterSpec> ivSpecSupplier = ivParameterSpecSupplier == null ? () -> null
: ivParameterSpecSupplier;
String transformation = CryptoUtil.transformation(algorithmName, mode, padding);
return new BouncyCastleBlockCipher(transformation, secretKeySpecSupplier, ivSpecSupplier, calculator, verifier);
return new BouncyCastleQuickCipher(transformation, secretKeySpecSupplier, ivSpecSupplier, calculator, verifier);
}

}
Loading

0 comments on commit 65d5b40

Please sign in to comment.