Skip to content

Commit

Permalink
Merge branch 'feature/fe-crypt' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
John-Chan committed Sep 16, 2024
2 parents ec513c4 + 7162e92 commit 00b4876
Show file tree
Hide file tree
Showing 30 changed files with 790 additions and 240 deletions.
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 00b4876

Please sign in to comment.