blob: 156b04844f2b1dbbe8200be73a73bb417cf5fac8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.shardingsphere.encrypt.algorithm.standard;
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.spi.EncryptAlgorithm;
import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithmMetaData;
import org.apache.shardingsphere.infra.algorithm.core.context.AlgorithmSQLContext;
import org.apache.shardingsphere.infra.algorithm.core.exception.AlgorithmInitializationException;
import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.Base64;
import java.util.Properties;
/**
* AES encrypt algorithm.
*/
@EqualsAndHashCode
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 final EncryptAlgorithmMetaData metaData = new EncryptAlgorithmMetaData(true, true, false, getDefaultProperties());
private byte[] secretKey;
private Properties getDefaultProperties() {
Properties result = new Properties();
result.setProperty(DIGEST_ALGORITHM_NAME, MessageDigestAlgorithms.SHA_1);
return result;
}
@Override
public void init(final Properties props) {
Properties properties = new Properties(metaData.getDefaultProps());
properties.putAll(props);
secretKey = getSecretKey(properties);
}
private byte[] getSecretKey(final Properties props) {
String aesKey = props.getProperty(AES_KEY);
ShardingSpherePreconditions.checkNotEmpty(aesKey, () -> new AlgorithmInitializationException(this, "%s can not be null or empty", AES_KEY));
String digestAlgorithm = props.getProperty(DIGEST_ALGORITHM_NAME);
return Arrays.copyOf(DigestUtils.getDigest(digestAlgorithm.toUpperCase()).digest(aesKey.getBytes(StandardCharsets.UTF_8)), 16);
}
@SneakyThrows(GeneralSecurityException.class)
@Override
public String encrypt(final Object plainValue, final AlgorithmSQLContext algorithmSQLContext) {
if (null == plainValue) {
return null;
}
byte[] result = getCipher(Cipher.ENCRYPT_MODE).doFinal(String.valueOf(plainValue).getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(result);
}
@SneakyThrows(GeneralSecurityException.class)
@Override
public Object decrypt(final Object cipherValue, final AlgorithmSQLContext algorithmSQLContext) {
if (null == cipherValue) {
return null;
}
byte[] result = getCipher(Cipher.DECRYPT_MODE).doFinal(Base64.getDecoder().decode(cipherValue.toString().trim()));
return new String(result, StandardCharsets.UTF_8);
}
private Cipher getCipher(final int decryptMode) throws GeneralSecurityException {
Cipher result = Cipher.getInstance(getType());
result.init(decryptMode, new SecretKeySpec(secretKey, getType()));
return result;
}
@Override
public String getType() {
return "AES";
}
}