对脱敏内容进行模糊查询解决办法

简介: 对脱敏内容进行模糊查询解决办法

在现代信息化社会中,数据安全问题越来越受到人们的关注。尤其是一些敏感字段,如用户密码、身份证号码、银行卡号等,如果直接存储在数据库中,一旦数据库被攻破,则这些敏感数据就会被窃取。为了保障数据安全,许多应用程序会将这些敏感字段进行加密存储。但是,加密后的敏感字段如何进行模糊查询呢?本篇博客将介绍加密后的敏感字段进行模糊查询的最佳解决办法。

加密算法的选择
在进行加密存储之前,我们需要选择合适的加密算法。一般来说,加密算法可以分为对称加密算法和非对称加密算法两种。

对称加密算法
对称加密算法是指加密和解密使用相同的密钥。常见的对称加密算法有DES、3DES、AES等。对称加密算法的优点是加密解密速度快,适合对大量数据进行加密。但是,由于加密和解密使用相同的密钥,如果密钥泄露,则数据将无法保密。

非对称加密算法
非对称加密算法是指加密和解密使用不同的密钥。常见的非对称加密算法有RSA、DSA等。非对称加密算法的优点是密钥管理方便,不容易泄露。但是,由于加密和解密使用不同的密钥,加密解密速度较慢,适合对少量数据进行加密。

哈希算法
除了对称加密算法和非对称加密算法,还有一种支持模糊查询的哈希算法。哈希算法是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。常见的哈希算法有MD5、SHA1、SHA256等。哈希算法的优点是可以将任意长度的消息压缩成固定长度的摘要,且不可逆,不同的消息会得到不同的摘要。因此,可以将敏感数据进行哈希处理后存储在数据库中,即使数据库被攻破,攻击者也无法得到原始数据。

数据库存储方式的选择
在选择加密算法之后,我们需要选择合适的数据库存储方式。常见的数据库存储方式有明文存储和加密存储两种。

明文存储
明文存储是指将原始数据直接存储在数据库中。这种方式的优点是存储和查询速度快,但是安全性较差,容易被攻击者窃取敏感数据。

加密存储
加密存储是指将原始数据进行加密后存储在数据库中。这种方式的优点是安全性较高,即使数据库被攻破,攻击者也无法得到原始数据。但是,由于加密解密需要消耗一定的计算资源,因此存储和查询速度较慢。

模糊查询的实现
在选择加密算法和数据库存储方式之后,我们需要考虑如何进行模糊查询。常见的模糊查询方式有通配符匹配和正则表达式匹配两种。

通配符匹配
通配符匹配是指使用通配符来匹配字符串。常见的通配符有“”和“?”。“”表示匹配任意字符序列(包括空字符序列),“?”表示匹配任意单个字符。例如,如果要查询所有以“abc”开头的字符串,可以使用“abc*”进行匹配。

通配符匹配的优点是简单易用,适合对少量数据进行查询。但是,由于通配符匹配需要遍历所有的数据,因此查询速度较慢。

正则表达式匹配
正则表达式匹配是指使用正则表达式来匹配字符串。正则表达式是一种描述字符序列特征的语言,可以用来匹配、查找和替换字符串。例如,如果要查询所有以“abc”开头的字符串,可以使用“^abc.*”进行匹配。

正则表达式匹配的优点是灵活性高,可以匹配各种复杂的字符串模式。但是,由于正则表达式匹配需要消耗大量的计算资源,因此查询速度较慢。

加密算法和数据库存储方式的优化
在实际应用中,我们需要根据实际需求和安全性要求进行权衡,选择合适的解决方案。同时,我们还可以通过优化加密算法和数据库存储方式来提高查询速度。

索引优化
索引是一种用于加速数据库查询的数据结构。常见的索引包括B树、B+树、哈希表等。如果我们选择了哈希算法进行加密存储,可以使用哈希表来优化查询速度。哈希表是一种基于哈希函数实现的数据结构,可以快速地进行查找操作。同时,我们还可以使用数据库的索引功能来优化查询速度,例如使用B+树索引来加速查询。

哈希表优化
如果我们选择了哈希算法进行加密存储,可以使用哈希表来优化查询速度。哈希表是一种基于哈希函数实现的数据结构,可以快速地进行查找操作。在哈希表中,每个数据项都有一个对应的索引值,通过索引值可以快速地查找到对应的数据项。如果查询条件中包含通配符,可以将通配符转换为正则表达式,并使用正则表达式匹配来优化查询速度。

例子
首先,我们需要使用非对称加密算法对敏感字段进行加密。在本例中,我们使用RSA算法对字符串进行加密。

import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import javax.crypto.Cipher;

public class RSAUtil {
// 生成公钥和私钥对
public static KeyPair generateKeyPair(int keySize) throws Exception {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(keySize);
return keyPairGenerator.generateKeyPair();
}

// 加密
public static byte[] encrypt(byte[] data, PublicKey publicKey) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.ENCRYPT_MODE, publicKey);
    return cipher.doFinal(data);
}

// 解密
public static byte[] decrypt(byte[] data, PrivateKey privateKey) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE, privateKey);
    return cipher.doFinal(data);
}

}

然后,我们需要使用SHA-256哈希算法对加密后的敏感字段进行哈希处理。在本例中,我们使用Java自带的MessageDigest类实现SHA-256哈希算法。

import java.security.MessageDigest;

public class HashUtil {
// 哈希处理
public static byte[] hash(byte[] data) throws Exception {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
messageDigest.update(data);
return messageDigest.digest();
}
}
接下来,我们需要使用Java的JDBC API连接数据库,并将加密后的敏感字段存储在数据库中。在本例中,我们使用MySQL数据库,并使用JDBC API实现数据库连接和数据存储。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBUtil {
// 数据库连接信息
private static final String URL = "jdbc:mysql://localhost:3306/test";
private static final String USER = "root";
private static final String PASSWORD = "123456";

// 数据库连接
public static Connection getConnection() throws SQLException {
    return DriverManager.getConnection(URL, USER, PASSWORD);
}

// 数据库查询
public static ResultSet query(String sql, Object... params) throws SQLException {
    Connection connection = getConnection();
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    for (int i = 0; i < params.length; i++) {
        preparedStatement.setObject(i + 1, params[i]);
    }
    return preparedStatement.executeQuery();
}

// 数据库插入
public static int insert(String sql, Object... params) throws SQLException {
    Connection connection = getConnection();
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    for (int i = 0; i < params.length; i++) {
        preparedStatement.setObject(i + 1, params[i]);
    }
    return preparedStatement.executeUpdate();
}

}

然后,我们需要实现模糊查询功能。在本例中,我们使用通配符匹配的方式实现模糊查询。

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public class SearchUtil {
// 模糊查询
public static List search(String keyword) throws Exception {
byte[] hash = HashUtil.hash(RSAUtil.encrypt(keyword.getBytes(), publicKey));
ResultSet resultSet = DBUtil.query("SELECT * FROM user WHERE hash LIKE ?", "%" + bytesToHexString(hash) + "%");
List result = new ArrayList<>();
while (resultSet.next()) {
byte[] encryptedName = hexStringToBytes(resultSet.getString("name"));
byte[] name = RSAUtil.decrypt(encryptedName, privateKey);
result.add(new String(name));
}
return result;
}

// 字节数组转十六进制字符串
public static String bytesToHexString(byte[] bytes) {
    StringBuilder stringBuilder = new StringBuilder();
    for (byte b : bytes) {
        String hex = Integer.toHexString(b & 0xFF);
        if (hex.length() == 1) {
            stringBuilder.append("0");
        }
        stringBuilder.append(hex);
    }
    return stringBuilder.toString();
}

// 十六进制字符串转字节数组
public static byte[] hexStringToBytes(String hexString) {
    Pattern pattern = Pattern.compile("^([0-9a-fA-F]{2})+$");
    if (!pattern.matcher(hexString).matches()) {
        throw new IllegalArgumentException("Invalid hexadecimal string");
    }
    byte[] bytes = new byte[hexString.length() / 2];
    for (int i = 0; i < bytes.length; i++) {
        bytes[i] = (byte) Integer.parseInt(hexString.substring(i * 2, i * 2 + 2), 16);
    }
    return bytes;
}

}

最后,我们需要在程序入口处生成公钥和私钥,并使用公钥加密敏感字段,将加密后的敏感字段存储在数据库中。在本例中,我们使用Java的main方法作为程序入口。

import java.security.KeyPair;

public class Main {
private static PublicKey publicKey;
private static PrivateKey privateKey;

public static void main(String[] args) throws Exception {
    // 生成公钥和私钥对
    KeyPair keyPair = RSAUtil.generateKeyPair(2048);
    publicKey = keyPair.getPublic();
    privateKey = keyPair.getPrivate();

    // 加密敏感字段并存储到数据库中
    String name = "张三";
    byte[] encryptedName = RSAUtil.encrypt(name.getBytes(), publicKey);
    byte[] hash = HashUtil.hash(encryptedName);
    DBUtil.insert("INSERT INTO user (name, hash) VALUES (?, ?)", bytesToHexString(encryptedName), bytesToHexString(hash));

    // 模糊查询敏感字段
    String keyword = "三";
    List<String> result = SearchUtil.search(keyword);
    System.out.println(result);
}

// 字节数组转十六进制字符串
public static String bytesToHexString(byte[] bytes) {
    StringBuilder stringBuilder = new StringBuilder();
    for (byte b : bytes) {
        String hex = Integer.toHexString(b & 0xFF);
        if (hex.length() == 1) {
            stringBuilder.append("0");
        }
        stringBuilder.append(hex);
    }
    return stringBuilder.toString();
}

}

总结
加密后的敏感字段进行模糊查询是一个比较复杂的问题,需要综合考虑加密算法、数据库存储方式和查询方式等多个因素。在实际应用中,我们需要根据实际需求和安全性要求进行权衡,选择合适的解决方案。同时,我们还可以通过优化加密算法和数据库存储方式来提高查询速度。
公众号请关注"果酱桑", 一起学习,一起进步!

目录
相关文章
|
存储 SQL 安全
加密后的数据如何进行模糊查询?
在数据安全和隐私保护日益重要的今天,加密技术成为保护敏感数据的重要手段。然而,加密后的数据在存储和传输过程中虽然安全性得到了提升,但如何对这些数据进行高效查询,尤其是模糊查询,成为了一个挑战。本文将深入探讨如何在保证数据安全的前提下,实现加密数据的模糊查询功能。
1656 0
element-plus:el-date-picker日期只选择年月不要日
element-plus:el-date-picker日期只选择年月不要日
1595 0
|
数据采集 SQL 分布式计算
数据处理 、大数据、数据抽取 ETL 工具 DataX 、Kettle、Sqoop
数据处理 、大数据、数据抽取 ETL 工具 DataX 、Kettle、Sqoop
2682 0
|
1月前
|
存储 人工智能 安全
做了半年自动化后,我才发现飞书多维表格解决的不是表格问题
飞书多维表格是自动化利器,无需代码即可实现数据收集、存储与流程触发。它与n8n无缝对接,表单提交自动触发工作流,数据实时同步,既是起点也是终点,真正实现高效协作与全自动处理,让复杂变简单。
|
11月前
|
Prometheus 监控 Cloud Native
高频面题: 你们线上 QPS 多少?你 怎么知道的?
本文由45岁资深架构师尼恩撰写,针对高级开发和架构师面试中的高频问题提供详细解答。文章涵盖了QPS、TPS、RT等性能指标的定义及计算方法,详解了如何配置Prometheus与Grafana监控系统QPS,并提供了应对高并发场景(如双十一抢购)的系统部署策略。此外,还分享了多个大厂面试真题及解决方案,帮助读者在面试中充分展示技术实力,提升求职竞争力。建议收藏并深入学习,为面试做好充分准备。更多内容可参考《尼恩Java面试宝典》及相关技术圣经系列PDF。
|
SQL XML JavaScript
【若依Java】15分钟玩转若依二次开发,新手小白半小时实现前后端分离项目,springboot+vue3+Element Plus+vite实现Java项目和管理后台网站功能
摘要: 本文档详细介绍了如何使用若依框架快速搭建一个基于SpringBoot和Vue3的前后端分离的Java管理后台。教程涵盖了技术点、准备工作、启动项目、自动生成代码、数据库配置、菜单管理、代码下载和导入、自定义主题样式、代码生成、启动Vue3项目、修改代码、以及对代码进行自定义和扩展,例如单表和主子表的代码生成、树形表的实现、商品列表和分类列表的改造等。整个过程详细地指导了如何从下载项目到配置数据库,再到生成Java和Vue3代码,最后实现前后端的运行和功能定制。此外,还提供了关于软件安装、环境变量配置和代码自动生成的注意事项。
28846 73
Axure原型设计:制作验证码倒计时,并重新获取交互效果
本文详细介绍了在Axure中实现验证码倒计时交互效果的步骤,包括元件准备、布局美化、全局变量设置及交互效果配置。通过分解交互流程,利用全局变量控制倒计时逻辑,最终实现按钮从“获取验证码”到倒计时状态的自动切换,并可重复使用。
431 1
|
缓存 NoSQL Java
Spring Boot中的高并发处理
Spring Boot中的高并发处理
|
数据采集 人工智能 监控
Spring Boot项目中集成Spring AI(也就是Spring Artificial Intelligence)
Spring Boot项目中集成Spring AI(也就是Spring Artificial Intelligence)
5479 1