Hive UDF实现数据加密解密功能

1 AES算法

AES(Advanced Encryption Standard)即高级加密标准,是一种对称加密算法,被广泛应用于数据加密和保护领域。AES算法使用的密钥长度为128位、192位或256位,比DES算法的密钥长度更长,安全性更高。

2 自定义UDF函数

利用AES算法自定义UDF函数,实现在Hive中数据的加密解密功能

1)在POM中添加依赖

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-exec</artifactId>
            <version>2.3.7</version>
        </dependency>
    </dependencies>

2)加密函数

/**
 * @description: 加密函数
 * @author: mayx
 * @create: 2023-05-03 11:31
 **/
@Description(name = "encrypt", value = "_FUNC_(Object, string = 'default_key') - decrypt Object with the key string",
             extended = "Example:\n" +
                "SELECT decrypt('18366668888', '1234567890123456') as phone; \n" +
                "SELECT decrypt(18366668888) as phone;\n")
public class AESDecrypt extends UDF {

    private static final String DEFAULT_KEY = "1qaz@WSX3edc$RFV";
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";

    /**
     * 只有一个参数,参数为要加密的内容,秘钥为默认值
     * @param arg 要加密的内容
     * @return
     */
    public  String evaluate(Object arg) {
        String str = String.valueOf(arg);
        if (str != null && !str.isEmpty()) {
            return evaluate(str, DEFAULT_KEY);
        }
        return "";
    }

    /**
     *
     * @param arg 要加密的内容
     * @param key 密钥
     * @return 加密后的字符串
     */
    public  String evaluate(Object arg, String key) {
        String str = String.valueOf(arg);
        try {
            if (str == null) {
                return null;
            }
            if (str.isEmpty()) {
                return "";
            }
            if (key == null || key.isEmpty()) {
                return evaluate(str);
            }
            // 密钥长度不足16位时,在末尾补零
            if (key.length() < 16) {
                key = key + "0000000000000000".substring(0, 16 - key.length());
            }
            // 密钥长度超过16位时,从开头截取16位
            else if (key.length() > 16) {
                key = key.substring(0, 16);
            }
            // 创建用于加密的密钥规范对象
            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), ALGORITHM);
            // 创建加密器对象并指定算法、工作模式和填充方式
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);

            if (cipher == null || secretKey == null) {
                return "";
            }
            // 初始化加密器对象,并设置加密模式和密钥
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            // 对原始字符串进行加密,并使用Base64编码
            byte[] encryptedBytes  = cipher.doFinal(str.getBytes("UTF-8"));
            // 对加密后的数据使用Base64编码
            return Base64.getEncoder().encodeToString(encryptedBytes );
        } catch (NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException | UnsupportedEncodingException var5) {
            return null;
        }
    }
}

3)解密函数

/**
 * @description: 解密函数
 * @author: mayx
 * @create: 2023-05-03 14:29
 **/
@Description(name = "encrypt", value = "_FUNC_(string1, string2 = 'default_key') - encrypt string1 with the key string2",
             extended = "Example:\n" +
                     "SELECT encrypt('rVJWlhqOmtlqHZe007LITQ==', '1234567890123456') as phone;\n" +
                     "SELECT encrypt('4iUXY6/ZEeK2HmedjRhpoA==') as phone;")
public class AESEncrypt extends UDF {

    private static final String DEFAULT_KEY = "1qaz@WSX3edc$RFV";
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";

    public String evaluate(String str) {
        if (str != null && !str.isEmpty()) {
            return evaluate(str, DEFAULT_KEY);
        }
        return "";
    }

    // 解密方法,接收一个字符串参数和一个密钥参数,返回解密后的字符串
    public String evaluate(String str, String key) {
        try {
            if (str == null) {
                return null;
            }
            if (str.isEmpty()) {
                return "";
            }
            if (key == null || key.isEmpty()) {
                return evaluate(str);
            }
            // 密钥长度不足16位时,在末尾补零
            if (key.length() < 16) {
                key = key + "0000000000000000".substring(0, 16 - key.length());
            }
            // 密钥长度超过16位时,从开头截取16位
            else if (key.length() > 16) {
                key = key.substring(0, 16);
            }
            // 创建用于解密的密钥规范对象
            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes("UTF-8"), ALGORITHM);
            // 创建解密器对象并指定算法、工作模式和填充方式
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            if (cipher == null || secretKey == null) {
                return "";
            }
            // 初始化解密器对象,并设置解密模式和密钥
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            // 将加密后的字符串先使用Base64解码,然后解密
            byte[] original = cipher.doFinal(Base64.getDecoder().decode(str));
            return new String(original,"UTF-8");
        } catch (NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException | UnsupportedEncodingException var5) {
            return null;
        }
    }
}

3 创建临时函数

1)打成jar包上传到服务器/opt/module/hive/datas/myudf.jar

在这里插入图片描述

2)将jar包添加到hive的classpath,临时生效

hive (default)> add jar /opt/module/hive/datas/encryptanddecrypt-1.0-SNAPSHOT.jar;

3)创建临时函数与开发好的java class关联

## 创建临时加密函数
hive (default)> create temporary function AESDecrypt as "com.mayx.udf.AESDecrypt";

## 创建临时加密函数
hive (default)> create temporary function AESEncrypt as "com.mayx.udf.AESEncrypt";

4)测试使用

hive (default)> select AESDecrypt('abc','1234567890');

hive (default)> select AESEncrypt('uI77ybGx1Oid6ues2O6lSQ==','1234567890');

在这里插入图片描述

5)删除临时函数

hive (default)> drop temporary function AESDecrypt;

hive (default)> drop temporary function AESEncrypt;

注意:临时函数只跟会话有关系,跟库没有关系。只要创建临时函数的会话不断,在当前会话下,任意一个库都可以使用,其他会话全都不能使用。

4 创建永久函数

注意:因为add jar本身也是临时生效,所以在创建永久函数的时候,需要制定路径(并且因为元数据的原因,这个路径还得是HDFS上的路径)。

1)将自定义UDF函数上传到HDFS上

hadoop fs -put /opt/module/hive/datas/encryptanddecrypt-1.0-SNAPSHOT.jar "hdfs://hadoop201:8020/udf/"

2)创建永久函数

create function AESDecrypt as "com.mayx.udf.AESDecrypt" 
using jar "hdfs://hadoop201:8020/udf/encryptanddecrypt-1.0-SNAPSHOT.jar";

create function AESEncrypt as "com.mayx.udf.AESEncrypt" 
using jar "hdfs://hadoop201:8020/udf/encryptanddecrypt-1.0-SNAPSHOT.jar";

3)删除永久函数

hive (default)> drop temporary function AESDecrypt;

hive (default)> drop temporary function AESEncrypt;

注意:永久函数跟会话没有关系,创建函数的会话断了以后,其他会话也可以使用。
永久函数创建的时候,在函数名之前需要自己加上库名,如果不指定库名的话,会默认把当前库的库名给加上。
永久函数使用的时候,需要在指定的库里面操作,或者在其他库里面使用的话加上,库名.函数名。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值