1.写java代码,打jar包

hivesql aes 加密 hive aes_encrypt_hive

1.pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zmlearn.udf</groupId>
    <artifactId>udf</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
    <dependency>
        <!-- hive的udf依赖的包 -->
        <groupId>org.apache.hive</groupId>
        <artifactId>hive-exec</artifactId>
        <version>2.1.0</version>
    </dependency>
    </dependencies>
    <!-- 打包类的依赖的jar的插件 -->
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>




</project>

2. AES对称加密和解密类

package com.zmlearn.udf;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Scanner;

/*
 * AES对称加密和解密
 */
public class AES {

    public static final String ENCODE_RULES = "8DFC34B0B7C98EFA0A299A6C3FFFBD9D";
    /*
     * 加密
     * 1.构造密钥生成器
     * 2.根据ecnodeRules规则初始化密钥生成器
     * 3.产生密钥
     * 4.创建和初始化密码器
     * 5.内容加密
     * 6.返回字符串
     */
    public static String AESEncode(String encodeRules,String content){
        try {
            //1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen=KeyGenerator.getInstance("AES");
            //2.根据ecnodeRules规则初始化密钥生成器
            //生成一个128位的随机源,根据传入的字节数组
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(encodeRules.getBytes());
            keygen.init(128, random);            //3.产生原始对称密钥
            SecretKey original_key=keygen.generateKey();
            //4.获得原始对称密钥的字节数组
            byte [] raw=original_key.getEncoded();
            //5.根据字节数组生成AES密钥
            SecretKey key=new SecretKeySpec(raw, "AES");
            //6.根据指定算法AES自成密码器
            Cipher cipher=Cipher.getInstance("AES");
            //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.ENCRYPT_MODE, key);
            //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
            byte [] byte_encode=content.getBytes(StandardCharsets.UTF_8);
            //9.根据密码器的初始化方式--加密:将数据加密
            byte [] byte_AES=cipher.doFinal(byte_encode);
            //10.将加密后的数据转换为字符串
            //这里用Base64Encoder中会找不到包
            //解决办法:
            //在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。
            //11.将字符串返回
            return new BASE64Encoder().encode(byte_AES);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }

        //如果有错就返加nulll
        return null;
    }
    /*
     * 解密
     * 解密过程:
     * 1.同加密1-4步
     * 2.将加密后的字符串反纺成byte[]数组
     * 3.将加密内容解密
     */
    public static String AESDncode(String encodeRules,String content){
        try {
            //1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen=KeyGenerator.getInstance("AES");
            //2.根据ecnodeRules规则初始化密钥生成器
            //生成一个128位的随机源,根据传入的字节数组
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(encodeRules.getBytes());
            keygen.init(128, random);
            //3.产生原始对称密钥
            SecretKey original_key=keygen.generateKey();
            //4.获得原始对称密钥的字节数组
            byte [] raw=original_key.getEncoded();
            //5.根据字节数组生成AES密钥
            SecretKey key=new SecretKeySpec(raw, "AES");
            //6.根据指定算法AES自成密码器
            Cipher cipher=Cipher.getInstance("AES");
            //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.DECRYPT_MODE, key);
            //8.将加密并编码后的内容解码成字节数组
            byte [] byte_content= new BASE64Decoder().decodeBuffer(content);
            /*
             * 解密
             */
            byte [] byte_decode=cipher.doFinal(byte_content);
            return new String(byte_decode, StandardCharsets.UTF_8);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IOException | IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }

        //如果有错就返加nulll
        return null;
    }

    public static void main(String[] args) {
        Scanner scanner=new Scanner(System.in);
        /*
         * 加密
         */
        System.out.println("使用AES对称加密,请输入加密的规则");
        String encodeRules=scanner.next();
        System.out.println("请输入要加密的内容:");
        String content = scanner.next();
        System.out.println("根据输入的规则"+encodeRules+"加密后的密文是:"+ AESEncode(encodeRules, content));

        /*
         * 解密
         */
        System.out.println("使用AES对称解密,请输入加密的规则:(须与加密相同)");
        encodeRules=scanner.next();
        System.out.println("请输入要解密的内容(密文):");
        content = scanner.next();
        System.out.println("根据输入的规则"+encodeRules+"解密后的明文是:"+ AESDncode(encodeRules, content));
    }

}

3.UDF函数

package com.zmlearn.udf;
import org.apache.hadoop.hive.ql.exec.UDF;

public class AESUDF extends UDF{
    String password = "8DFC34B0B7C98EFA0A299A6C3FFFBD9D";

    public String evaluate ( String type , String content) throws Exception {
        if (content == null) return null;

        if(! type.equals("encode") && ! type.equals("decode")){
            throw new Exception("Parmeter one is needed encode/decode");
        }

        if( type.equals("encode")){
            //进行加密
            return AES.AESEncode (password, content);
        }else {
            //进行解密
            return AES.AESDncode(password, content);
        }
    }


    public static void main(String[] args) {

        try {
            System.out.println(new AESUDF().evaluate("encode","test"));
            System.out.println(new AESUDF().evaluate("decode","bkP4HSbPbL+yqViBjfvQJg=="));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.将打好的jar上传到hdfs

1.打包步骤

点击idea的Maven后,点击package。如下图

hivesql aes 加密 hive aes_encrypt_hive_02

2.将打包后的udf-1.0-SNAPSHOT.jar,上传到hdfs上面

#一定记得,不然创建函数的时候会报警Class com.zmlearn.udf.AESUDF not found,因为没有执行权限
chmod 777 /tmp/udf-1.0-SNAPSHOT.jar

hadoop fs -mkdir /hive_UDF

hadoop fs -put /root/data/udf-1.0-SNAPSHOT.jar /hive_UDF

hivesql aes 加密 hive aes_encrypt_hivesql aes 加密_03

3.进入hive客户端,创建UDF函数。

create function AES_UDF as 'com.zmlearn.udf.AESUDF' using jar 
'hdfs://nameservice1/hive_UDF/udf-1.0-SNAPSHOT.jar';

4.使用创建的UDF函数:

1.加密

insert overwrite table test2 partition(dt='2020-06-01')
select AES_UDF('encode',dnum),AES_UDF('encode',sn) from test1

2.解密

insert overwrite table test1 partition(dt='2020-06-01')
select AES_UDF('decode',dnum),AES_UDF('decode',sn) from test2