账号密码数据库加密说明

一、加密算法选择

密码学中两种常见的密码算法为:对称密码算法和非对称密码算法。

对称密钥加密,又称私钥加密,即信息的发送方和接收方用一个密钥去加密和解密数据。它的最大优势是加/解密速度快,适合于对大数据量进行加密,但密钥管理困难。

非对称密钥加密,又称公钥密钥加密。它需要使用一对密钥来分别完成加密和解密操作,一个公开发布,即公开密钥,另一个由用户自己秘密保存,即私用密钥。信息发送者用公开密钥去加密,而信息接收者则用私用密钥去解密。公钥机制灵活,但加密和解密速度却比对称密钥加密慢得多。

对称加密算法用来对敏感数据等信息进行加密,常用的算法包括:
DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合。
3DES(Triple DES):是基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高。
AES(Advanced Encryption Standard):高级加密标准,是下一代的加密算法标准,速度快,安全级别高;

Mysql官网手册

https://dev.mysql.com/doc/refman/5.7/en/encryption-functions.html#function_aes-encrypt

MySQL的内置加密函数里已经不推荐DES算法,所以选用AES算法来加解密账号密码。

二、加密策略

AES算法加解密都需要同一个key,如果这个key用来加密所有账号的密码,那么密码相同的不同账号得到的加密结果是相同的,这样会降低安全性,所以用可以唯一标识账号的aid来当做key,为了更不容易反向推导出key,实际应用中会用一个内部的salt字符串拼上账号aid来作为key。

三、实现

为了灵活和重用,没使用MySQL内置函数,改用Java实现。

AES算法实现与操作系统有关,本实现兼容Windows/Linux。

加密后获得的是byte[]类型结果,因此数据库内相应字段的类型应为BLOB,节省空间用TinyBlob类型就够。

加密算法需要使用外部类库javabase64-1.3.1.jar

Java实现有两个类:

AESUtils:提供加解密静态方法

Base64Utils :辅助AESUtils类

AESUtils常用方法说明:


方法


返回


说明


参数


getSecretKey(String seed)


String


生成key


seed: salt+aid


encrypt(byte[] data, String key)


byte[]


加密


data: 密码明文getBytes(“UTF-8”)

key: getScretKey方法结果


decrypt(byte[] data, String key)


byte[]


解密


data: 密码密文

key: getScretKey方法结果

AESUtils.java:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class AESUtils {

    private static final String ALGORITHM = "AES";
    private static final int KEY_SIZE = 128;
    private static final int CACHE_SIZE = 1024;

    public static String getSecretKey() throws Exception {
        return getSecretKey(null);
    }

    public static String getSecretKey(String seed) throws Exception {
        try {
            KeyGenerator _generator = KeyGenerator.getInstance(ALGORITHM);
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
            secureRandom.setSeed(seed.getBytes("UTF-8"));
            _generator.init(KEY_SIZE, secureRandom);
            SecretKey secretKey = _generator.generateKey();
            return Base64Utils.encode(secretKey.getEncoded());
        } catch (Exception e) {
            throw new RuntimeException("初始化密钥出现异常");
        }

    }

    public static byte[] encrypt(byte[] data, String key) throws Exception {
        Key k = toKey(Base64Utils.decode(key));
        byte[] raw = k.getEncoded();
        SecretKeySpec secretKeySpec = new SecretKeySpec(raw, ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        return cipher.doFinal(data);
    }

    public static void encryptFile(String key, String sourceFilePath, String destFilePath) throws Exception {
        File sourceFile = new File(sourceFilePath);
        File destFile = new File(destFilePath);
        if (sourceFile.exists() && sourceFile.isFile()) {
            if (!destFile.getParentFile().exists()) {
                destFile.getParentFile().mkdirs();
            }
            destFile.createNewFile();
            InputStream in = new FileInputStream(sourceFile);
            OutputStream out = new FileOutputStream(destFile);
            Key k = toKey(Base64Utils.decode(key));
            byte[] raw = k.getEncoded();
            SecretKeySpec secretKeySpec = new SecretKeySpec(raw, ALGORITHM);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            CipherInputStream cin = new CipherInputStream(in, cipher);
            byte[] cache = new byte[CACHE_SIZE];
            int nRead = 0;
            while ((nRead = cin.read(cache)) != -1) {
                out.write(cache, 0, nRead);
                out.flush();
            }
            out.close();
            cin.close();
            in.close();
        }
    }

    public static byte[] decrypt(byte[] data, String key) throws Exception {
        Key k = toKey(Base64Utils.decode(key));
        byte[] raw = k.getEncoded();
        SecretKeySpec secretKeySpec = new SecretKeySpec(raw, ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        return cipher.doFinal(data);
    }

    public static void decryptFile(String key, String sourceFilePath, String destFilePath) throws Exception {
        File sourceFile = new File(sourceFilePath);
        File destFile = new File(destFilePath);
        if (sourceFile.exists() && sourceFile.isFile()) {
            if (!destFile.getParentFile().exists()) {
                destFile.getParentFile().mkdirs();
            }
            destFile.createNewFile();
            FileInputStream in = new FileInputStream(sourceFile);
            FileOutputStream out = new FileOutputStream(destFile);
            Key k = toKey(Base64Utils.decode(key));
            byte[] raw = k.getEncoded();
            SecretKeySpec secretKeySpec = new SecretKeySpec(raw, ALGORITHM);
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            CipherOutputStream cout = new CipherOutputStream(out, cipher);
            byte[] cache = new byte[CACHE_SIZE];
            int nRead = 0;
            while ((nRead = in.read(cache)) != -1) {
                cout.write(cache, 0, nRead);
                cout.flush();
            }
            cout.close();
            out.close();
            in.close();
        }
    }

    private static Key toKey(byte[] key) throws Exception {
        SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);
        return secretKey;
    }
}

Base64Utils.java:

import it.sauronsoftware.base64.Base64;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class Base64Utils {

    private static final int CACHE_SIZE = 1024;

    public static byte[] decode(String base64) throws Exception {
        return Base64.decode(base64.getBytes("UTF-8"));
    }

    public static String encode(byte[] bytes) throws Exception {
        return new String(Base64.encode(bytes));
    }

    public static String encodeFile(String filePath) throws Exception {
        byte[] bytes = fileToByte(filePath);
        return encode(bytes);
    }

    public static void decodeToFile(String filePath, String base64) throws Exception {
        byte[] bytes = decode(base64);
        byteArrayToFile(bytes, filePath);
    }

    public static byte[] fileToByte(String filePath) throws Exception {
        byte[] data = new byte[0];
        File file = new File(filePath);
        if (file.exists()) {
            FileInputStream in = new FileInputStream(file);
            ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
            byte[] cache = new byte[CACHE_SIZE];
            int nRead = 0;
            while ((nRead = in.read(cache)) != -1) {
                out.write(cache, 0, nRead);
                out.flush();
            }
            out.close();
            in.close();
            data = out.toByteArray();
        }
        return data;
    }

    public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
        InputStream in = new ByteArrayInputStream(bytes);
        File destFile = new File(filePath);
        if (!destFile.getParentFile().exists()) {
            destFile.getParentFile().mkdirs();
        }
        destFile.createNewFile();
        OutputStream out = new FileOutputStream(destFile);
        byte[] cache = new byte[CACHE_SIZE];
        int nRead = 0;
        while ((nRead = in.read(cache)) != -1) {
            out.write(cache, 0, nRead);
            out.flush();
        }
        out.close();
        in.close();
    }

}
时间: 2024-11-02 23:31:33

账号密码数据库加密说明的相关文章

使用selenium进行密码破解(绕过账号密码JS加密)

经常碰到网站,账号密码通过js加密后进行提交.通过burp拦截抓到的账号密码是加密后的,所以无法通过burp instruder进行破解.只能模拟浏览器填写表单并点击登录按钮进行破解.于是想到了自动化web测试工具selenium,代码如下,测试效果还不错. package com.example.tests; import java.util.regex.Pattern;import java.io.BufferedReader;import java.io.File;import java.

kylin的配置账号密码的加密方法

kylin的配置账号密码的加密方法 kylin安装过程中,配置账户,其中密码是加密的.生成密码对应密文的 方法如下: import java.io.PrintStream; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; public class KylinPas

对登录中账号密码进行加密之后再传输的爆破的思路和方式

一. 概述 渗透测试过程中遇到web登录的时候,现在很多场景账号密码都是经过js加密之后再请求发送(通过抓包可以看到加密信息)如图一burp抓到的包,request的post的登录包,很明显可以看到password参数的值是经过前端加密之后再进行传输的,遇到这种情况,普通发包的爆破脚本就很难爆破成功.鉴于这种情况,这边分析四种方式进行绕过加密爆破. 二. 方法和思路 1. 分析找出是哪个js文件进行了password参数值的加密,将该js导入本地动态执行,建一个小型的web服务器,利用浏览器页面

cas-简单的验证cas服务器登录和读取数据库账号密码登录

环境win8+tomcat7+jdk7+cas-server-4.0.0-release 1. 首先到 http://downloads.jasig.org/ 地址下载 cas-server-4.0.0-release.zip,解压后到modules目录中找到cas-server-webapp-4.0.0.war,复制到tomcat的webapp目录下,修改名称为cas.war 2. (1)创建证书 keytool -genkey -alias mycas -keyalg RSA -keysiz

修改servu数据库密码 servu加密方式

项目要求可以有用户自行修改servu密码.servu可以通过odbc访问access\mysql\sqlserver数据库.我们直接通过创建web来修改就可以了. 不过问题来了,密码是加密的...通过网上搜索找到了.net版本的加密方式...自己验证没问题... 下面贴出简单的测试代码(引用他人博客) servu加密:using System;using System.Collections.Generic;using System.Linq;using System.Web;using Sys

Nodejs通过账号密码连接MongoDB数据库

转自https://blog.csdn.net/szu_lzz/article/details/77435804#commentBox 1.创建管理员 首先开启Mongo服务,然后切换admin数据库,一开始是没有这个数据库的. > use admin 1 2.然后创建用户和密码: > db.createUser({user:'root',pwd:'root1234',roles:['root']}) 1 3.创建了管理员账号和密码之后,然后运行Mongo服务的时候加上 –auth参数: mo

493万Gmail用户的账号密码遭泄露,疑从其他网站数据库提炼而成

据国外媒体报道,周二近493万的Gmail用户账号和密码被发布到了俄罗斯的比特币论坛上.发布这些账号密码的比特币论坛用户,表示这其中约60%是有效的.不过谷歌公司并不认为Gmail有任何安全漏洞. 谷歌方面发言人表示,目前并没有证据表明,谷歌的系统被入侵过.一旦发现任何帐户有可能已经受到安全威胁,谷歌方面将会采取适当措施对其进行保护.同时,谷歌建议用户启用两步验证,并给出建议 “不管你是否是在名单上,换掉你的密码,以防万一.” 随后,论坛的管理员对这些账号中的文本内容进行了清理,只留下了用户名等

zf-关于更改账号密码的问题

一般项目的数据库里都会有一个 SYS_USER表 里面有账号密码 一般 202……70 的都是123加密后的字符串 如果碰到项目运行之后不知道登陆密码的时候 可以在数据库中 把USER_PASS 改成这个字段 '202cb962ac59075b964b07152d234b70'

账号密码管理系统Access版本

哈哈,花了我整整五天时间,账号密码管理系统软件终于成功编写完成了.由于我的各大论坛的账号密码特别多,记性又不好.所以一直以来都想要这么一个软件的,但是以前学习的都是面向过程的编程语言,一直无法实现这个想法.这个暑假为了做一个程序项目,对记事本实现图形用户界面增删改查操作,所以开始学习C#编程.在花了整整二十天学习Winform编程和研究文件读写流(大多数时间在学习文件读写流上,Winform编程也就学会了几个常用的控件,文件读写流这个边读边写刚开始不会,特别蛋疼),好在经过一番努力学习后终于实现