1、需求 mysql的敏感字段,在同步到从库时,利用aes加密存储在从库。2、方法

package com.alibaba.otter;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Objects;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang.StringUtils;
import com.alibaba.otter.node.extend.processor.AbstractEventProcessor;
import com.alibaba.otter.shared.etl.model.EventColumn;
import com.alibaba.otter.shared.etl.model.EventData;
import com.alibaba.otter.shared.etl.model.EventType;
public class TransferProcessor extends AbstractEventProcessor {
private static final String DEFAULT_KEY = "223081629e274cecaxxxxxx"; //秘钥
public boolean process(EventData eventData) {
String eventType = eventData.getEventType().getValue();
if (eventType.equals(EventType.QUERY.getValue())) {
return true;
}
ColumnInfoEnum[] values = ColumnInfoEnum.values();
for (ColumnInfoEnum cie : values) {
EventColumn column = getColumn(eventData, cie.getColumnKey());
if (Objects.nonNull(column)) {
if (StringUtils.isNotBlank(column.getColumnValue())) {
column.setColumnValue(aes_encrypt(column.getColumnValue(), DEFAULT_KEY));
}
}
}
return true;
}
/******************************
* 字符串转字节数组 开始
****************************************/
/**
*
* mysql 加密一直的SecretKeySpec
*
* @param key
*
* @return
*
*/
public static SecretKeySpec gener(String key) {
try {
byte[] finalKey = new byte[16];
int i = 0;
for (byte b : key.getBytes("utf-8")) {
finalKey[i++ % 16] ^= b;
}
return new SecretKeySpec(finalKey, "AES");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
public static String aes_encrypt(String password, String strKey) {
try {
byte[] keyBytes = Arrays.copyOf(strKey.getBytes("ASCII"), 16);
// 通用的
// SecretKey key = new SecretKeySpec(keyBytes, "AES");
// 生成和mysql一直的加密数据
SecretKeySpec key = gener(strKey);
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cleartext = password.getBytes("UTF-8");
byte[] ciphertextBytes = cipher.doFinal(cleartext);
return new String(Hex.encodeHexString(ciphertextBytes));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static SecretKeySpec generateMySQLAESKey(final String key, final String encoding) {
try {
final byte[] finalKey = new byte[16];
int i = 0;
for (byte b : key.getBytes(encoding))
finalKey[i++ % 16] ^= b;
return new SecretKeySpec(finalKey, "AES");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public static String aes_decrypt(String content, String aesKey) {
try {
SecretKey key = generateMySQLAESKey(aesKey, "ASCII");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] cleartext = Hex.decodeHex(content.toCharArray());
byte[] ciphertextBytes = cipher.doFinal(cleartext);
return new String(ciphertextBytes, "UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/******************************
* 字符串转字节数组 结束
****************************************/
private String replace(String sourceValue, int prefixLength, int subffixLength) {
sourceValue = sourceValue.trim();
if (StringUtils.isBlank(sourceValue)) {
return "";
}
int length = sourceValue.length();
if (length < (prefixLength + subffixLength)) {
return "";
}
sourceValue = sourceValue.replaceAll("(\\s)", "*");
System.out.println(sourceValue);
int placeHolderLenth = length - prefixLength - subffixLength;
String pattern = "(\\S{" + (prefixLength) + "})\\S{" + placeHolderLenth + "}(\\S{" + subffixLength + "})";
StringBuilder placeHolder = new StringBuilder("$1");
for (int i = 0; i < placeHolderLenth; i++) {
placeHolder.append("*");
}
placeHolder.append("$2");
return sourceValue.replaceAll(pattern, placeHolder.toString());
}
enum ColumnInfoEnum {
FIRST_NAME("first_name",1,0),
FULL_NAME("full_name",1,0),
LAST_NAME("last_name",1,0); //将要加密的字段放在这,后面的数字没啥用
ColumnInfoEnum(String columnKey, int prefixLength, int subffixLength) {
this.columnKey = columnKey;
this.prefixLength = prefixLength;
this.subffixLength = subffixLength;
}
private String columnKey;
private int prefixLength;
private int subffixLength;
public String getColumnKey() {
return columnKey;
}
public int getPrefixLength() {
return prefixLength;
}
public int getSubffixLength() {
return subffixLength;
}
}
}
这样,数据就可以加密存储在从库中了:
可以用mysql的自带函数解密

