Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(encryption): stream encryption #18

Merged
merged 4 commits into from
Mar 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.ghcr.heliannuuthus.devtools.controller;

import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.stream.Stream;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/crypto")
@Tag(name = "encrypt/decrypt api")
public class EncryptionController {

@GetMapping("/encryption")
public Flux<String> algorithm() {
return Flux.fromStream(Stream.of("AES", "RSA-OAEP", "ECIES"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
import static io.ghcr.heliannuuthus.devtools.crypto.parameters.OamParameters.*;

import io.ghcr.heliannuuthus.devtools.crypto.ParametersFactory;
import io.ghcr.heliannuuthus.devtools.crypto.Signature;
import io.ghcr.heliannuuthus.devtools.crypto.Signer;
import io.ghcr.heliannuuthus.devtools.crypto.algorithms.MessageDigest;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.AsymmetricParameters;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.SignParameters;
import io.ghcr.heliannuuthus.devtools.model.dto.SignatureRequest;
import io.ghcr.heliannuuthus.devtools.model.dto.VerificationRequest;
import io.swagger.v3.oas.annotations.Operation;
Expand All @@ -23,12 +23,12 @@
@RestController
@AllArgsConstructor
@RequestMapping("/crypto")
@Tag(name = "signature api")
@Tag(name = "sign/verify api")
public class SignatureController {

private final Signature signature;
private final Signer signature;

@GetMapping("/algorithms")
@GetMapping("/signature")
@Operation(summary = "fetch signature algorithm")
public Flux<String> algorithms() {
return Flux.fromStream(
Expand All @@ -38,17 +38,17 @@ public Flux<String> algorithms() {
.flatMap(
alg ->
Stream.of(MessageDigest.values())
.map(md -> md.getName() + CONNECTOR + alg))));
.map(md -> md.getValue() + CONNECTOR + alg))));
}

@PostMapping("/sign")
@Operation(summary = "sign api")
public Mono<String> sign(@Valid @RequestBody SignatureRequest request) {
return Mono.fromCallable(
() -> {
AsymmetricParameters parameters =
SignParameters parameters =
ParametersFactory.getInstance()
.create(
.createForSign(
request.getAlgorithm(),
request.getKeyFormat().decode(request.getKey()),
true);
Expand All @@ -64,9 +64,9 @@ public Mono<String> sign(@Valid @RequestBody SignatureRequest request) {
public Mono<Boolean> verify(@Valid @RequestBody VerificationRequest request) {
return Mono.fromCallable(
() -> {
AsymmetricParameters parameters =
SignParameters parameters =
ParametersFactory.getInstance()
.create(
.createForSign(
request.getAlgorithm(),
request.getKeyFormat().decode(request.getKey()),
false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
import static io.ghcr.heliannuuthus.devtools.exception.CryptoException.DECRYPT_MODE;
import static io.ghcr.heliannuuthus.devtools.exception.CryptoException.ENCRYPT_MODE;

import io.ghcr.heliannuuthus.devtools.crypto.parameters.BlockParameters;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.EncryptionParameters;
import io.ghcr.heliannuuthus.devtools.exception.CryptoException;
import javax.crypto.Cipher;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Component;

@Component
public class BlockCipher {
public byte[] encrypt(byte[] plaintext, BlockParameters parameters) {
public class Encryptor {
public byte[] encrypt(byte[] plaintext, EncryptionParameters parameters) {
try {
Cipher cipher =
Cipher.getInstance(parameters.getAlgorithm(), BouncyCastleProvider.PROVIDER_NAME);
Expand All @@ -22,7 +22,7 @@ public byte[] encrypt(byte[] plaintext, BlockParameters parameters) {
}
}

public byte[] decrypt(byte[] cypher, BlockParameters parameters) {
public byte[] decrypt(byte[] cypher, EncryptionParameters parameters) {
try {
Cipher cipher =
Cipher.getInstance(parameters.getAlgorithm(), BouncyCastleProvider.PROVIDER_NAME);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@

import com.google.common.collect.Sets;
import io.ghcr.heliannuuthus.devtools.crypto.algorithms.MessageDigest;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.AsymmetricParameters;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.EncryptionParameters;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.SignParameters;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.ecdsa.ECCParameters;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.ecdsa.ECIESParameters;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.eddsa.Ed25519Parameters;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.eddsa.Ed448Parameters;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.rsa.RSAParameters;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.rsa.RSAStreamParameters;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.sm2.SM2Parameters;
import io.ghcr.heliannuuthus.devtools.exception.BadRequestException;
import java.util.Set;
Expand All @@ -19,11 +22,6 @@
public class ParametersFactory {

private static final ParametersFactory INSTANCE = new ParametersFactory();

public static ParametersFactory getInstance() {
return INSTANCE;
}

private static final Set<String> RSA =
Stream.of(MessageDigest.values())
.map(md -> md + CONNECTOR + RSA_ALGORITHM)
Expand All @@ -39,7 +37,11 @@ public static ParametersFactory getInstance() {
.map(md -> md + CONNECTOR + SM2_ALGORITHM)
.collect(Collectors.toSet());

public AsymmetricParameters create(String algorithm, byte[] key, boolean forSign) {
public static ParametersFactory getInstance() {
return INSTANCE;
}

public SignParameters createForSign(String algorithm, byte[] key, boolean forSign) {
if (RSA.contains(algorithm)) {
return new RSAParameters(key, forSign);
} else if (ECC.contains(algorithm)) {
Expand All @@ -54,6 +56,15 @@ public AsymmetricParameters create(String algorithm, byte[] key, boolean forSign
} else if (GM.contains(algorithm)) {
return new SM2Parameters(key, forSign);
}
throw new BadRequestException("unsupported algorithm " + algorithm);
throw new BadRequestException("unsupported stream sign algorithm " + algorithm);
}

public EncryptionParameters createForEncrypt(String algorithm, byte[] key, boolean forEncrypt) {
if (RSA.contains(algorithm)) {
return new RSAStreamParameters(key, !forEncrypt);
} else if (ECC.contains(algorithm)) {
return new ECIESParameters(key, !forEncrypt);
}
throw new BadRequestException("unsupported stream encrypt algorithm " + algorithm);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package io.ghcr.heliannuuthus.devtools.crypto;

import io.ghcr.heliannuuthus.devtools.crypto.parameters.AsymmetricParameters;
import io.ghcr.heliannuuthus.devtools.crypto.parameters.SignParameters;
import io.ghcr.heliannuuthus.devtools.exception.CryptoException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Component;

@Component
public class Signature {
public byte[] sign(byte[] plaintext, AsymmetricParameters parameters) {
public class Signer {
public byte[] sign(byte[] plaintext, SignParameters parameters) {
try {
java.security.Signature signer =
java.security.Signature.getInstance(
Expand All @@ -20,7 +20,7 @@ public byte[] sign(byte[] plaintext, AsymmetricParameters parameters) {
}
}

public boolean verify(byte[] plaintext, byte[] signature, AsymmetricParameters parameters) {
public boolean verify(byte[] plaintext, byte[] signature, SignParameters parameters) {
try {
java.security.Signature signer =
java.security.Signature.getInstance(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

@Getter
@AllArgsConstructor
public enum Padding {
public enum AESEncryptionPadding {
PKCS7("PKCS7Padding"),
PKCS5("PKCS5Padding"),
None("NoPadding");
private final String name;
private final String value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
public enum MessageDigest {
NONE("None"),
SM3("SM3"),
SHA_1("SHA1"),
SHA_256("SHA256"),
SHA_384("SHA384"),
SHA_512("SHA512");

private final String name;
SHA_512("SHA512"),
SHA3_256("SHA3-256"),
SHA3_384("SHA3-384"),
SHA3_512("SHA3-512");
private final String value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.ghcr.heliannuuthus.devtools.crypto.algorithms;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum RSAEncryptionPadding {
OAEP_SHA1("OAEPWithSHA-1AndMGF1Padding", MessageDigest.SHA_1),
OAEP_SHA256("OAEPWithSHA-256AndMGF1Padding", MessageDigest.SHA_256),
OAEP_SHA3_256("OAEPWithSHA3-256AndMGF1Padding", MessageDigest.SHA3_256),
OAEP_SHA3_384("OAEPWithSHA3-384AndMGF1Padding", MessageDigest.SHA3_384),
OAEP_SHA3_512("OAEPWithSHA3-512AndMGF1Padding", MessageDigest.SHA3_512),
OAEP_SHA384("OAEPWithSHA-384AndMGF1Padding", MessageDigest.SHA_384),
OAEP_SHA512("OAEPWithSHA-512AndMGF1Padding", MessageDigest.SHA_512),
PKCSV1_5("PKCS1Padding", null);
private final String value;
private final MessageDigest md;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.ghcr.heliannuuthus.devtools.crypto.parameters;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public abstract class BlockEncryptionParameters implements EncryptionParameters {

protected byte[] key;

public abstract String getMode();

public SecretKey getKey() {
return new SecretKeySpec(this.key, getName());
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.ghcr.heliannuuthus.devtools.crypto.parameters;

import com.google.common.base.Joiner;
import io.ghcr.heliannuuthus.devtools.crypto.algorithms.AESEncryptionPadding;
import java.security.Key;
import java.security.spec.AlgorithmParameterSpec;

public interface EncryptionParameters extends OamParameters {

String NONE_MODE = "NONE";
String ECB_MODE = "ECB";
String CBC_MODE = "CBC";
String GCM_MODE = "GCM";

Key getKey();

@Override
default String getAlgorithm() {
return Joiner.on("/").skipNulls().join(getName(), getMode(), getPadding());
}

default String getName() {
return null;
}

String getMode();

default String getPadding() {
return AESEncryptionPadding.PKCS7.getValue();
}

default AlgorithmParameterSpec getSpec() {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ public interface OamParameters {
String ECDSA_ALGORITHM = "ECDSA";
String SM2_ALGORITHM = "SM2";

String ECIES_ALGORITHM = "ECIES";
String ECDH_ALGORITHM = "ECDH";

String CONNECTOR = "with";

String getAlgorithm();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
import org.bouncycastle.jce.provider.BouncyCastleProvider;

@Getter
public abstract class AsymmetricParameters implements OamParameters {
public abstract class SignParameters implements OamParameters {

private MessageDigest messageDigest = MessageDigest.SHA_256;

protected AsymmetricParameters() {}
protected SignParameters() {}

public AsymmetricParameters(byte[] key, boolean isPrivate) {
public SignParameters(byte[] key, boolean isPrivate) {
this();
try {
KeyFactory keyFactory =
Expand All @@ -32,7 +32,7 @@ public AsymmetricParameters(byte[] key, boolean isPrivate) {
}
}

public AsymmetricParameters(byte[] privateKey, byte[] publicKey) {
public SignParameters(byte[] privateKey, byte[] publicKey) {
try {
KeyFactory keyFactory =
KeyFactory.getInstance(this.getName(), BouncyCastleProvider.PROVIDER_NAME);
Expand All @@ -49,10 +49,10 @@ public AsymmetricParameters(byte[] privateKey, byte[] publicKey) {
public abstract String getName();

public String getMessageDigest() {
return messageDigest.getName();
return messageDigest.getValue();
}

public AsymmetricParameters md(MessageDigest messageDigest) {
public SignParameters md(MessageDigest messageDigest) {
this.messageDigest = messageDigest;
return this;
}
Expand Down
Loading