生成id + 编码 + 常见的加密算法及 Java 实现

分布式全局ID生成器-雪花算法 - QiaoZhi - 博客园(重要)

Java中简单的获取UUID

示例代码:

UUID的标准型式包含32个16进位数字,以连字号分为五段,形式为8-4-4-4-12的32个字符,加上“-”一共是36位,所以咱们可以先取出uuid,再把“-”去掉。

String str = UUID.randomUUID().toString().replace("-", "").toUpperCase();

图解:

常用编码方式:

Hex base64 urlencode三种方式编码方案

 hex,base64,urlencode编码方案对比_hex字符-CSDN博客()

常见的加密算法及 Java 实现:

一:Base64加密

Base64算法并不是加密算法,属于编码格式,是一种基于64个可打印字符来表示二进制数据的方法。作为网络上最常见的用于传输Bit字节代码的编码方式之一。

Base64的使用场景:

Base64用于在HTTP环境下传递较长的标识信息。由于Base64的可逆性,通常我们在项目中将报文进行压缩、加密后,最后一步必然是使用base64编码,因为base64编码的字符串,更适合不同平台、不同语言的传输。我们一般不单独用Base64作为加密解密方法。

例如:存储图片为base64格式的字符串,建议前端直接传给后端base64的照片字符串,或者后台拿到照片后处理成base64入库,然后给前端返回base64的图片。

二:单向加密(不可逆)

常见的单向加密有:MD5、SHA算法

该算法在加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,密文无法解密。只有重新输入明文,并经过同样的加密算法处理,得到相同的密文并被系统重新识别后,才能真正解密。

1、MD5加密
MD5全称是Message-Digest Algoorithm 5(信息-摘要算法),也是目前最主流的算法。

首先得明确的是,MD5是生成了信息摘要,为了确保信息完整性的一种摘要算法。MD5的典型应用是对一段Message(字节串)产生fingerprint(指纹),以防止被“篡改”。举个例子,系统为了确保你就是你,给你生成了一枚指纹,每次通过指纹识别,能判断你的身份。

通过这种特性,MD5加密使用场景:

1、文件完整性校验
当我们在某个资源下载网站,下载一份资料的时候,怎么判断你下载的资源就是网站提供的呢?这个时候就利用MD5,做一次MD5校验,以确保我们获得的文件与该站点提供的数字签名(Message-Digest)

文件为同一文件。举个例子,你将一段消息写在一个叫 content.txt文件中,对content.txt做一次MD5校验,产生一个MD5的值并记录,然后你可以传播这个文件给别人,别人如果修改了文件中的任何内容,你对这个文件重新计算MD5时就会发现(两个MD5值不相同)。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,或者防止文件被篡改,这就是所谓的数字签名应用。

2、操作系统的登录认证
如在UNIX系统中用户的密码是以MD5(或其它类似的算法)经Hash运算后存储在文件系统中。当用户登录的时候,系统把用户输入的密码进行MD5 Hash运算,然后再去和保存在文件系统中的MD5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这可以避免用户的密码被具有系统管理员权限的用户知道。MD5将任意长度的“字节串”映射为一个128bit的大整数,并且是通过该128bit反推原始字符串是困难的,换句话说就是,即使你看到源程序和算法描述,也无法将一个MD5的值变换回原始的字符串,从数学原理上说,是因为原始的字符串有无穷多个,这有点象不存在反函数的数学函数。所以,要遇到了md5密码的问题,比较好的办法是:你可以用这个系统中的md5()函数重新设一个密码,如admin,把生成的一串密码的Hash值覆盖原来的Hash值就行了。

如何破解MD5呢?

尽管现在各种MD5破解工具层出不穷,但是MD5依然是常用,并且十分有效的加密手段。MD5还没有办法被逆向计算,最怕的就是“碰撞”。通俗讲,就是我在本地将“123456”,做一次MD5运算,生成了16位的信息摘要“49BA59ABBE56E057”,或者32位的“E10ADC3949BA59ABBE56E057F20F883E”,有一天我破解了数据库,得到了你的MD5运算密码,恰好是“E10ADC3949BA59ABBE56E057F20F883E”,那就碰撞上了,得知你的明文为“123456”。MD5碰撞的方法有很多,主要包括暴力枚举法、字典法、彩虹表法等等。

暴力枚举法顾名思义,就是简单粗暴地枚举出所有原文,并计算出它们的哈希值,看看哪个哈希值和给定的信息摘要一致。这种方法虽然简单,但是时间复杂度极高。想象一下,仅仅长度8位的密码就有多少种排列组合的可能性?

如果说暴力枚举法是ongoing时间换空间,那么字典法则是用空间换时间。黑客利用一个巨大的字典,存储尽可能多的原文和对应的哈希值。每次用给定的信息摘要查找字典,即可快速找到碰撞的结果。

彩虹表法较为麻烦,首先,假设要破解的密文位于某一链条的k-1位置处,对其进行Rk运算,看是否能够在末节点中找到对应的值。如果找到,则可以如前所述,使用起节点验证其正确性。否则,继续假设密文位于k-2位置处,这时就需要进行Rk-1、H、Rk两步运算,然后在末节点中查找结果。如是反复,最不利条件下需要将密文进行完整的R1、H、…Rk运算后,才能得知密文是否存在于彩虹表之中。

怎么保证不被碰撞破解呢?

加入盐值(salt)即可,只要明文相同,那么生成的MD5码就相同,于是攻击者就可以通过撞库的方式来破解出明文。加盐就是向明文中加入随机数,然后在生成MD5,这样一来即使明文相同,但由于随机数是不同(极少相同),所以每次生成的MD5码也不同,如此一来就大大增加了暴力破解的难度,使其几乎不可能破解。

2、SHA

SHA (英文名:Secure Hash Algorithm,中文名:安全散列算法),是一种密码散列函数,美国国家安全局设计。其家族还是很庞大的,有SHA-0、SHA-1、SHA-2、SHA-3等4类型算法。

其中,SHA-2 包括了SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256等算法。

SHA-3 包括了SHA3-224 、SHA3-256 、SHA3-384 、SHA3-512、SHAKE128 、SHAKE256等算法。

SHA1:全称是安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准(Digital Signature Standard DSS)里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。近些年来随着算力的增强,SHA1被证实存在弱点,许多组织建议用SHA-2或SHA-3来替换SHA-1。SHA-1是一种数据加密算法,该算法的思想是接收一段明文,然后以一种不可逆的方式将它转换成一段(通常更小)密文,也可以简单的理解为取一串输入码(称为预映射或信息),并把它们转化为长度较短、位数固定的输出序列即散列值(也称为信息摘要或信息认证代码)的过程。

SHA256:SHA-256算法常用于密码存储、数字签名等场景,因为它提供了高强度的安全性和不可逆性。

三:对称加密(可逆)

同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。

DES( Data Encryption Standard ) 是一种数据加密标准。

通常用KeyGenerator初始化此密钥生成器,使其具有确定的密钥大小,然后实例化DES密钥规则,利用Cipher类加密。

3DES,即3重DES,是DES的一个分支,密钥长度更长;但由于安全性问题;且违反柯克霍夫原则,使用频率低。

AES,可以使用128、192、和256位密钥,并且用128位分组加密和解密数据。近些年DES使用越来越少,原因就在于其使用56位密钥,比较容易被破解,逐渐被AES替代相较于DES,  AES的特点是一个SK扩展成多个子SK,轮加密。

Rabbit流密码(Rabbit Stream Cipher),密钥长度128位,最大加密消息长度为264 Bytes,即16 TB,若消息超过该长度,则需要更换密钥对剩下的消息进行处理。目前没有找到更详细的资料。

四:非对称加密

RSA是被研究得最广泛的公钥算法,从提出到现在已近三十年,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。RSA公开密钥密码体制的原理是:根据数论,寻求两个大素数比较简单,而将它们的乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。明文和密文均是0至n-1之间的证书,n的大小通常为1024位的2进制,或309位的十进制。使用RSA一般需要产生公钥和私钥,当采用公钥加密时,使用私钥解密;采用私钥加密时,使用公钥解密。 RSA的公钥和私钥到底哪个才是用来加密和哪个用来解密? - 知乎(优质)

你只要想:既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证

RSA2是采用SHA256WithRSA作为标准签名算法的,RSA采用SHA1WithRSA,强制要求 RSA 密钥的长度至少为 2048。

RSA的公钥私钥的加密解密博客: java加解密之RSA使用

SpringCloud-Gateway实现RSA加解密_gateway rsa数据加密-CSDN博客(优质博客)

RSA密钥的数据类型转换:由合法的string到PublicKey或PrivateKey_rsapublickey与string互转-CSDN博客

PKCS8格式是RSA加密方式Java调用的格式

PKCS1是标准RSA秘钥对标准规范,但是都是裸奔的; PKCS8是对加密后的秘钥进行了描述,就是说P8格式的秘钥不是裸奔了

五. 算法实现(java)

MD5三种方式加密(16位大小、32位大小),base64两种方式加解密整理 - 简书(参考博客)

Java实现md5加密有三种方式可供选择
1.Spring自带DigestUtils(优点,方便,代码简洁,缺点只可进行MD5加密)

spring自带jar包

        import org.springframework.util.DigestUtils;

        //32位,小写
        String md532Lower = DigestUtils.md5DigestAsHex("adcdefg".getBytes());
        //32位,大写
        String md532Upper=md532Lower.toUpperCase();
        //16位,小写
        String md516Lower =md532Lower.substring(8, 24);
        //16位,大写
        String md516Upper=md532Lower.substring(8, 24).toUpperCase();
2.Java自带MessageDigest(优点,可以加密多种算法如:MD5,SHA,SHA1,SHA-224,SHA-256,SHA-384,SHA-512,缺点代码语句较多,不方便)

 public static void getMD5Str(String str) {
        MessageDigest messageDigest = null;

        try {
            messageDigest = MessageDigest.getInstance("MD5");

            messageDigest.reset();

            messageDigest.update(str.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            System.out.println("NoSuchAlgorithmException caught!");
            System.exit(-1);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        byte[] byteArray = messageDigest.digest();

        StringBuffer md5StrBuff = new StringBuffer();

        for (int i = 0; i < byteArray.length; i++) {
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
                md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
            else
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
        }
        //32位,小写
        String md532Lower = md5StrBuff.toString();
        //32位,大写
        String md532Upper=md532Lower.toUpperCase();
        //16位,小写
        String md516Lower =md532Lower.substring(8, 24);
        //16位,大写
        String md516Upper=md532Lower.substring(8, 24).toUpperCase();
    }
3.apache的DigestUtils(优点,代码简洁,缺点,只能MD5加密,额外引用maven依赖或手动导入jar)

           <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.3.2</version>
            </dependency>

import org.apache.commons.codec.digest.DigestUtils

public static void md5(String text) throws Exception {
        // 加密后的字符串
        String md5str = DigestUtils.md5Hex(text);
        //32位,小写
        String md532Lower = md5str.toString();
        //32位,大写
        String md532Upper=md532Lower.toUpperCase();
        //16位,小写
        String md516Lower =md532Lower.substring(8, 24);
        //16位,大写
        String md516Upper=md532Lower.substring(8, 24).toUpperCase();
    }

最后整理了一点关于MD5解密如下:

MD5解密本质上并非真正的破解,只是加速了杂凑冲撞。通俗点说,知道一个MD5串,然后使用原文进行MD5散列后再生成同样的MD5串,也就是说找到不同的原文产生相同MD5串的方法,这不是解密而称之为碰撞。MD5只有128位要真能解密的话,就变成一个超级压缩工具了!

网络上流行的MD5解密工具和在线解密网站,通常只是针对用户密码,或比较简单的数字进行破解,其方法是将常用字符串的MD5密码保存到数据库,然后再与待解密的字符串做对比,最终找到匹配的源码。

现在被黑客使用最多的一种破译密码的方法就是一种被称为"跑字典"的方法。有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用MD5程序计算出这些字典项的MD5值,然后再用目标的MD5值在这个字典中检索。我们假设密码的最大长度为8位字节(8 Bytes),同时密码只能是字母和数字,共26+26+10=62个字符,排列组合出的字典的项数则是P(62,1)+P(62,2)….+P(62,8),那也已经是一个很天文的数字了,存储这个字典就需要TB级的磁盘阵列,而且这种方法还有一个前提,就是能获得目标账户的密码MD5值的情况下才可以。这种加密技术被广泛的应用于UNIX系统中,这也是为什么UNIX系统比一般操作系统更为坚固一个重要原因。

base64两种加解密方式
1.利用Java中sun.misc.BASE64Encoder()


import org.apache.commons.codec.binary.Base64;
import org.springframework.util.Assert;
import sun.plugin2.util.SystemUtil;
 
import java.io.IOException;
 
/**
 * Created by crj on 2016/9/27.
 */
public class Base64Encrypt {
    /**
     * 编码
     *
     * @param bstr
     * @return String
     */
    public static String encode(byte[] bstr) {
        return new sun.misc.BASE64Encoder().encode(bstr);
    }
 
    /**
     * 解码
     *
     * @param str
     * @return string
     */
    public static byte[] decode(String str) {
        byte[] bt = null;
        try {
            sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
            bt = decoder.decodeBuffer(str);
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        return bt;
    }
}
2.利用Java中Base64.encodeBase64()

import org.apache.commons.codec.binary.Base64;
import org.springframework.util.Assert;
import sun.plugin2.util.SystemUtil;
import java.io.IOException;
public class Base64Encrypt {
    public static void main(String[] args) {
        String base64String = "whuang123";
        byte[] result1= Base64.encodeBase64(base64String.getBytes());
        String str11=new String(result1);
        byte[] result2 = Base64.decodeBase64(result1);
        String str12=new String(result2);
        System.out.println(str11+"-------"+str12);
    }
}



作者:叫我靓仔啦
链接:https://www.jianshu.com/p/ad69e4067841
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Base64(可以解密)

public static void main(String[] args) {
    try {
        // 编码
        String encode = Base64.getEncoder().encodeToString("son".getBytes("UTF-8"));
        System.out.println(encode);  //打印结果:c29u
        // 解码
        byte[] decode = Base64.getDecoder().decode("c29u");
        System.out.println(new String(decode, "UTF-8"));    //打印结果:son
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    }
}

MD5 和 SHA 家族(不可逆)

public static void main(String[] args) {
    
    String content = "you are my son"; // 原文
    try {
        byte[] a;
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
        a = messageDigest.digest(content.getBytes());
        System.out.println(byte2hex(a)); // 333a9634d8809b5a9e8d280d82553b8fd8d4a911

        messageDigest = MessageDigest.getInstance("SHA-256");
        a = messageDigest.digest(content.getBytes());
        System.out.println(byte2hex(a)); // cdb2c97079d9a1943eea98de4201f5c4f49ecda5af2b364e1c7a5d1ae89688eb

        messageDigest = MessageDigest.getInstance("MD5");
        a = messageDigest.digest(content.getBytes());
        System.out.println(byte2hex(a)); // 6fe6b9a8f8bd29f4f4f1368a0619a7ae

        // 第三方 MD5 算法。需要添加 jar 包 org.apache.commons.codec.digest.DigestUtils
        String encodeStr=DigestUtils.md5Hex(content);
        System.out.println(encodeStr); // 6fe6b9a8f8bd29f4f4f1368a0619a7ae

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}

public static String byte2hex(byte[] b) //二进制转字符串
{
    String hs = "";
    String stmp = "";
    for (int n = 0; n < b.length; n++) {
        stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
        if (stmp.length() == 1) {
            hs = hs + "0" + stmp;
        } else {
            hs = hs + stmp;
        }
    }
    return hs;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,接下来是利用RSA算法加解密学号的JAVA代码实现。 请先确保你已经安装了Java环境,并且导入了Bouncy Castle加密库。如果还没有安装和导入,可以自行在网上搜索教程。 1. 加密学号 ```java import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.interfaces.RSAPublicKey; import javax.crypto.Cipher; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class RSAEncrypt { public static void main(String[] args) { try { String studentId = "1234567890"; // 待加密的学号 byte[] plainText = studentId.getBytes(); // 初始化加密环境 Security.addProvider(new BouncyCastleProvider()); KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC"); kpg.initialize(4096, new SecureRandom()); // 生成RSA密钥对 KeyPair keyPair = kpg.generateKeyPair(); RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 使用公钥加密 Cipher cipher = Cipher.getInstance("RSA", "BC"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] cipherText = cipher.doFinal(plainText); System.out.println("Encrypted student id: " + new BigInteger(cipherText)); } catch (Exception e) { e.printStackTrace(); } } } ``` 2. 解密学号 ```java import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.interfaces.RSAPrivateKey; import javax.crypto.Cipher; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class RSADecrypt { public static void main(String[] args) { try { BigInteger encryptedStudentId = new BigInteger("1234567890"); // 已加密的学号 // 初始化解密环境 Security.addProvider(new BouncyCastleProvider()); KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC"); kpg.initialize(4096, new SecureRandom()); // 生成RSA密钥对 KeyPair keyPair = kpg.generateKeyPair(); PrivateKey privateKey = keyPair.getPrivate(); // 使用私钥解密 Cipher cipher = Cipher.getInstance("RSA", "BC"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] plainText = cipher.doFinal(encryptedStudentId.toByteArray()); System.out.println("Decrypted student id: " + new String(plainText)); } catch (Exception e) { e.printStackTrace(); } } } ``` 以上就是基于RSA算法加解密学号的JAVA代码实现,希望能对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值