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

add encrypt metadata for algorithm #29737

Merged
merged 8 commits into from
Jan 17, 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
Expand Up @@ -21,25 +21,37 @@ package org.apache.shardingsphere.example.${package}.${framework?replace('-', '.
import lombok.Getter;
import lombok.Setter;
import org.apache.shardingsphere.encrypt.api.context.EncryptContext;
import org.apache.shardingsphere.encrypt.api.encrypt.assisted.AssistedEncryptAlgorithm;
import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm;
import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithmMetaData;

import java.util.Properties;

@SuppressWarnings("LombokGetterMayBeUsed")
public final class TestQueryAssistedShardingEncryptAlgorithm implements AssistedEncryptAlgorithm {
public final class TestQueryAssistedShardingEncryptAlgorithm implements EncryptAlgorithm {

@Getter
private Properties properties;


@Getter
private EncryptAlgorithmMetaData metaData;

@Override
public void init(final Properties props) {
this.properties = props;
EncryptAlgorithmMetaData algorithmMetaData = new EncryptAlgorithmMetaData();
algorithmMetaData.setSupportDecrypt(false);
metaData = algorithmMetaData;
}

@Override
public String encrypt(final Object plainValue, final EncryptContext encryptContext) {
return "assistedEncryptValue";
}

@Override
public Object decrypt(final Object cipherValue, final EncryptContext encryptContext) {
throw new UnsupportedOperationException(String.format("Algorithm `%s` is unsupported to decrypt", getType()));
}

@Override
public String getType() {
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,20 @@ public interface EncryptAlgorithm extends ShardingSphereAlgorithm {
* @return cipher value
*/
Object encrypt(Object plainValue, EncryptContext encryptContext);

/**
* Decrypt.
*
* @param cipherValue cipher value
* @param encryptContext encrypt context
* @return plain value
*/
Object decrypt(Object cipherValue, EncryptContext encryptContext);

/**
* Get meta data.
*
* @return meta data.
*/
EncryptAlgorithmMetaData getMetaData();
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,25 @@
* limitations under the License.
*/

package org.apache.shardingsphere.encrypt.api.encrypt.assisted;
package org.apache.shardingsphere.encrypt.spi;

import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;

/**
* Assisted encrypt algorithm.
* Encrypt algorithm meta data.
*/
public interface AssistedEncryptAlgorithm extends EncryptAlgorithm {
@RequiredArgsConstructor
@Getter
public final class EncryptAlgorithmMetaData {

@Setter
private boolean supportDecrypt = true;

@Setter
private boolean supportEquivalentFilter = true;

@Setter
private boolean supportLike;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,32 +18,45 @@
package org.apache.shardingsphere.encrypt.algorithm.assisted;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.shardingsphere.encrypt.api.context.EncryptContext;
import org.apache.shardingsphere.encrypt.api.encrypt.assisted.AssistedEncryptAlgorithm;
import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm;
import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithmMetaData;

import java.util.Properties;

/**
* MD5 assisted encrypt algorithm.
*/
@EqualsAndHashCode
public final class MD5AssistedEncryptAlgorithm implements AssistedEncryptAlgorithm {
public final class MD5AssistedEncryptAlgorithm implements EncryptAlgorithm {

private static final String SALT_KEY = "salt";

private String salt;

@Getter
private EncryptAlgorithmMetaData metaData;

@Override
public void init(final Properties props) {
this.salt = props.getProperty(SALT_KEY, "");
EncryptAlgorithmMetaData encryptAlgorithmMetaData = new EncryptAlgorithmMetaData();
encryptAlgorithmMetaData.setSupportDecrypt(false);
metaData = encryptAlgorithmMetaData;
}

@Override
public String encrypt(final Object plainValue, final EncryptContext encryptContext) {
return null == plainValue ? null : DigestUtils.md5Hex(plainValue + salt);
}

@Override
public Object decrypt(final Object cipherValue, final EncryptContext encryptContext) {
throw new UnsupportedOperationException(String.format("Algorithm `%s` is unsupported to decrypt", getType()));
}

@Override
public String getType() {
return "MD5";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@

import com.google.common.base.Strings;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.SneakyThrows;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.MessageDigestAlgorithms;
import org.apache.shardingsphere.encrypt.api.context.EncryptContext;
import org.apache.shardingsphere.encrypt.api.encrypt.standard.StandardEncryptAlgorithm;
import org.apache.shardingsphere.encrypt.exception.algorithm.EncryptAlgorithmInitializationException;
import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm;
import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithmMetaData;
import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;

import javax.crypto.Cipher;
Expand All @@ -42,16 +44,20 @@
* AES encrypt algorithm.
*/
@EqualsAndHashCode
public final class AESEncryptAlgorithm implements StandardEncryptAlgorithm {
public final class AESEncryptAlgorithm implements EncryptAlgorithm {

private static final String AES_KEY = "aes-key-value";

private static final String DIGEST_ALGORITHM_NAME = "digest-algorithm-name";

@Getter
private EncryptAlgorithmMetaData metaData;

private byte[] secretKey;

@Override
public void init(final Properties props) {
metaData = new EncryptAlgorithmMetaData();
secretKey = createSecretKey(props);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public final class MismatchedEncryptAlgorithmTypeException extends EncryptSQLExc

private static final long serialVersionUID = 4258928279099223870L;

public MismatchedEncryptAlgorithmTypeException(final String databaseName, final String columnType, final String encryptorName, final String encryptAlgorithmType) {
super(XOpenSQLState.GENERAL_ERROR, 81, "`%s` column's encryptor name `%s` does not match encrypt algorithm type `%s` in database `%s`.",
columnType, encryptorName, encryptAlgorithmType, databaseName);
public MismatchedEncryptAlgorithmTypeException(final String databaseName, final String columnType, final String encryptorName, final String algorithmFeature) {
super(XOpenSQLState.GENERAL_ERROR, 81, "`%s` column's encryptor `%s` should support `%s` in database `%s`.",
columnType, encryptorName, algorithmFeature, databaseName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
package org.apache.shardingsphere.encrypt.rewrite.token.generator;

import lombok.Setter;
import org.apache.shardingsphere.encrypt.api.encrypt.standard.StandardEncryptAlgorithm;
import org.apache.shardingsphere.encrypt.constant.EncryptColumnDataType;
import org.apache.shardingsphere.encrypt.exception.metadata.EncryptColumnAlterException;
import org.apache.shardingsphere.encrypt.rewrite.aware.EncryptRuleAware;
Expand All @@ -29,6 +28,7 @@
import org.apache.shardingsphere.encrypt.rule.column.EncryptColumn;
import org.apache.shardingsphere.encrypt.rule.column.item.AssistedQueryColumnItem;
import org.apache.shardingsphere.encrypt.rule.column.item.LikeQueryColumnItem;
import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm;
import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
import org.apache.shardingsphere.infra.binder.context.statement.ddl.AlterTableStatementContext;
import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
Expand Down Expand Up @@ -176,8 +176,8 @@ private Collection<SQLToken> getChangeColumnTokens(final EncryptTable encryptTab
}

private void isSameEncryptColumn(final EncryptTable encryptTable, final String previousColumnName, final String columnName) {
Optional<StandardEncryptAlgorithm> previousEncryptor = encryptTable.findEncryptor(previousColumnName);
Optional<StandardEncryptAlgorithm> currentEncryptor = encryptTable.findEncryptor(columnName);
Optional<EncryptAlgorithm> previousEncryptor = encryptTable.findEncryptor(previousColumnName);
Optional<EncryptAlgorithm> currentEncryptor = encryptTable.findEncryptor(columnName);
if (!previousEncryptor.isPresent() && !currentEncryptor.isPresent()) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
import org.apache.shardingsphere.encrypt.api.config.EncryptRuleConfiguration;
import org.apache.shardingsphere.encrypt.api.config.rule.EncryptColumnRuleConfiguration;
import org.apache.shardingsphere.encrypt.api.config.rule.EncryptTableRuleConfiguration;
import org.apache.shardingsphere.encrypt.api.encrypt.assisted.AssistedEncryptAlgorithm;
import org.apache.shardingsphere.encrypt.api.encrypt.like.LikeEncryptAlgorithm;
import org.apache.shardingsphere.encrypt.api.encrypt.standard.StandardEncryptAlgorithm;
import org.apache.shardingsphere.encrypt.exception.algorithm.MismatchedEncryptAlgorithmTypeException;
import org.apache.shardingsphere.encrypt.exception.metadata.EncryptTableNotFoundException;
import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm;
Expand Down Expand Up @@ -56,16 +53,11 @@ public final class EncryptRule implements DatabaseRule, TableContainedRule {
public EncryptRule(final String databaseName, final EncryptRuleConfiguration ruleConfig) {
this.databaseName = databaseName;
configuration = ruleConfig;
Map<String, StandardEncryptAlgorithm> standardEncryptors = new LinkedHashMap<>();
Map<String, AssistedEncryptAlgorithm> assistedEncryptors = new LinkedHashMap<>();
Map<String, LikeEncryptAlgorithm> likeEncryptors = new LinkedHashMap<>();
ruleConfig.getEncryptors().forEach((key, value) -> putAllEncryptors(
key, TypedSPILoader.getService(EncryptAlgorithm.class, value.getType(), value.getProps()), standardEncryptors, assistedEncryptors, likeEncryptors));
Map<String, EncryptAlgorithm> encryptors = new LinkedHashMap<>();
ruleConfig.getEncryptors().forEach((key, value) -> encryptors.put(key, TypedSPILoader.getService(EncryptAlgorithm.class, value.getType(), value.getProps())));
for (EncryptTableRuleConfiguration each : ruleConfig.getTables()) {
each.getColumns().forEach(columnRuleConfig -> checkStandardEncryptorType(columnRuleConfig, standardEncryptors));
each.getColumns().forEach(columnRuleConfig -> checkAssistedQueryEncryptorType(columnRuleConfig, assistedEncryptors));
each.getColumns().forEach(columnRuleConfig -> checkLikeQueryEncryptorType(columnRuleConfig, likeEncryptors));
tables.put(each.getName().toLowerCase(), new EncryptTable(each, standardEncryptors, assistedEncryptors, likeEncryptors));
each.getColumns().forEach(columnRuleConfig -> checkEncryptorType(columnRuleConfig, encryptors));
tables.put(each.getName().toLowerCase(), new EncryptTable(each, encryptors));
tableNamesMapper.put(each.getName());
}
}
Expand All @@ -79,46 +71,24 @@ public EncryptRule(final String databaseName, final EncryptRuleConfiguration rul
public EncryptRule(final String databaseName, final CompatibleEncryptRuleConfiguration ruleConfig) {
this.databaseName = databaseName;
configuration = ruleConfig;
Map<String, StandardEncryptAlgorithm> standardEncryptors = new LinkedHashMap<>();
Map<String, AssistedEncryptAlgorithm> assistedEncryptors = new LinkedHashMap<>();
Map<String, LikeEncryptAlgorithm> likeEncryptors = new LinkedHashMap<>();
ruleConfig.getEncryptors().forEach((key, value) -> putAllEncryptors(
key, TypedSPILoader.getService(EncryptAlgorithm.class, value.getType(), value.getProps()), standardEncryptors, assistedEncryptors, likeEncryptors));
Map<String, EncryptAlgorithm> encryptors = new LinkedHashMap<>();
ruleConfig.getEncryptors().forEach((key, value) -> encryptors.put(key, TypedSPILoader.getService(EncryptAlgorithm.class, value.getType(), value.getProps())));
for (EncryptTableRuleConfiguration each : ruleConfig.getTables()) {
each.getColumns().forEach(columnRuleConfig -> checkStandardEncryptorType(columnRuleConfig, standardEncryptors));
each.getColumns().forEach(columnRuleConfig -> checkAssistedQueryEncryptorType(columnRuleConfig, assistedEncryptors));
each.getColumns().forEach(columnRuleConfig -> checkLikeQueryEncryptorType(columnRuleConfig, likeEncryptors));
tables.put(each.getName().toLowerCase(), new EncryptTable(each, standardEncryptors, assistedEncryptors, likeEncryptors));
tables.put(each.getName().toLowerCase(), new EncryptTable(each, encryptors));
tableNamesMapper.put(each.getName());
}
}

private void putAllEncryptors(final String encryptorName, final EncryptAlgorithm algorithm, final Map<String, StandardEncryptAlgorithm> standardEncryptors,
final Map<String, AssistedEncryptAlgorithm> assistedEncryptors, final Map<String, LikeEncryptAlgorithm> likeEncryptors) {
if (algorithm instanceof StandardEncryptAlgorithm) {
standardEncryptors.put(encryptorName, (StandardEncryptAlgorithm) algorithm);
}
if (algorithm instanceof AssistedEncryptAlgorithm) {
assistedEncryptors.put(encryptorName, (AssistedEncryptAlgorithm) algorithm);
}
if (algorithm instanceof LikeEncryptAlgorithm) {
likeEncryptors.put(encryptorName, (LikeEncryptAlgorithm) algorithm);
}
}

private void checkStandardEncryptorType(final EncryptColumnRuleConfiguration columnRuleConfig, final Map<String, StandardEncryptAlgorithm> standardEncryptors) {
ShardingSpherePreconditions.checkState(standardEncryptors.containsKey(columnRuleConfig.getCipher().getEncryptorName()),
() -> new MismatchedEncryptAlgorithmTypeException(databaseName, "Cipher", columnRuleConfig.getCipher().getEncryptorName(), StandardEncryptAlgorithm.class.getSimpleName()));
}

private void checkAssistedQueryEncryptorType(final EncryptColumnRuleConfiguration columnRuleConfig, final Map<String, AssistedEncryptAlgorithm> assistedEncryptors) {
columnRuleConfig.getAssistedQuery().ifPresent(optional -> ShardingSpherePreconditions.checkState(assistedEncryptors.containsKey(optional.getEncryptorName()),
() -> new MismatchedEncryptAlgorithmTypeException(databaseName, "Assisted query", optional.getEncryptorName(), AssistedEncryptAlgorithm.class.getSimpleName())));
}

private void checkLikeQueryEncryptorType(final EncryptColumnRuleConfiguration columnRuleConfig, final Map<String, LikeEncryptAlgorithm> likeEncryptors) {
columnRuleConfig.getLikeQuery().ifPresent(optional -> ShardingSpherePreconditions.checkState(likeEncryptors.containsKey(optional.getEncryptorName()),
() -> new MismatchedEncryptAlgorithmTypeException(databaseName, "Like query", optional.getEncryptorName(), LikeEncryptAlgorithm.class.getSimpleName())));
private void checkEncryptorType(final EncryptColumnRuleConfiguration columnRuleConfig, final Map<String, EncryptAlgorithm> encryptors) {
ShardingSpherePreconditions.checkState(encryptors.containsKey(columnRuleConfig.getCipher().getEncryptorName())
&& encryptors.get(columnRuleConfig.getCipher().getEncryptorName()).getMetaData().isSupportDecrypt(),
() -> new MismatchedEncryptAlgorithmTypeException(databaseName, "Cipher", columnRuleConfig.getCipher().getEncryptorName(), "decrypt"));
columnRuleConfig.getAssistedQuery().ifPresent(optional -> ShardingSpherePreconditions.checkState(encryptors.containsKey(optional.getEncryptorName())
&& encryptors.get(optional.getEncryptorName()).getMetaData().isSupportEquivalentFilter(),
() -> new MismatchedEncryptAlgorithmTypeException(databaseName, "Assisted query", columnRuleConfig.getCipher().getEncryptorName(), "equivalent filter")));
columnRuleConfig.getLikeQuery().ifPresent(optional -> ShardingSpherePreconditions.checkState(encryptors.containsKey(optional.getEncryptorName())
&& encryptors.get(optional.getEncryptorName()).getMetaData().isSupportLike(),
() -> new MismatchedEncryptAlgorithmTypeException(databaseName, "Like query", columnRuleConfig.getCipher().getEncryptorName(), "like")));
}

/**
Expand Down
Loading