Java密码

通过isoDep.transceive(byte[] commond)控制卡片(传输的byte[]为 APDU命令,该命令返回值后两个字节为报文处理结果,前边的内容为报文返回内容)

Java提供了KeyPairGenerator类。 此类用于生成公钥和私钥对。 要使用KeyPairGenerator类生成密钥,请按照以下步骤操作

第1步:创建KeyPairGenerator对象

KeyPairGenerator类提供getInstance()方法,该方法接受表示所需密钥生成算法的String变量,并返回生成密钥的KeyPairGenerator对象。

使用getInstance()方法创建KeyPairGenerator对象,如下所示。

//Creating KeyPair generator object
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA")

第2步:初始化KeyPairGenerator对象

KeyPairGenerator类提供了一个名为initialize()的方法,该方法用于初始化密钥对生成器。 此方法接受表示密钥大小的整数值。

使用此方法初始化在上一步中创建的KeyPairGenerator对象,如下所示。

//Creating KeyPair generator object
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");
//Initializing the KeyPairGenerator
keyPairGen.initialize(2048);

第3步:生成KeyPairGenerator

可以使用KeyPairGenerator类的generateKeyPair()方法生成KeyPair。 使用此方法生成密钥对,如下所示。

//Generate the pair of keys
KeyPair pair = keyPairGen.generateKeyPair();

作者: Maxsu Java技术QQ群:227270512 / Linux QQ群:479429477

 

 

 

Java提供了KeyPairGenerator类。 此类用于生成公钥和私钥对。 要使用KeyPairGenerator类生成密钥,请按照以下步骤操作。

第1步:创建KeyPairGenerator对象

KeyPairGenerator类提供getInstance()方法,该方法接受表示所需密钥生成算法的String变量,并返回生成密钥的KeyPairGenerator对象。

使用getInstance()方法创建KeyPairGenerator对象,如下所示。

//Creating KeyPair generator object
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");

Java

第2步:初始化KeyPairGenerator对象

KeyPairGenerator类提供了一个名为initialize()的方法,该方法用于初始化密钥对生成器。 此方法接受表示密钥大小的整数值。

使用此方法初始化在上一步中创建的KeyPairGenerator对象,如下所示。

//Creating KeyPair generator object
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DSA");
//Initializing the KeyPairGenerator
keyPairGen.initialize(2048);

Java

第3步:生成KeyPairGenerator

可以使用KeyPairGenerator类的generateKeyPair()方法生成KeyPair。 使用此方法生成密钥对,如下所示。

//Generate the pair of keys
KeyPair pair = keyPairGen.generateKeyPair();

Java

第4步:获取私钥/公钥

可以使用getPrivate()方法从生成的密钥对对象中获取私钥,如下所示。

//Getting the private key from the key pair
PrivateKey privKey = pair.getPrivate();

Java

可以使用getPublic()方法从生成的KeyPair对象获取公钥,如下所示。

//Getting the public key from the key pair
PublicKey publicKey = pair.getPublic();

DESedeKeySpec(byte[] key)
创建一个 DESedeKeySpec 对象,使用bai key 中的前du 24 个字节作为 DES-EDE 密钥的密zhi钥内容

执行数组拷贝
78          * System.arraycopy(源数组,从源数组哪里开始拷贝,目标数组,拷贝多少位)

(密钥长度都必须是8的倍数)

byte[] key = new byte[24];    //声明一个24位的字节数组,默认里面都是0
74         byte[] temp = keyStr.getBytes("UTF-8");    //将字符串转成字节数组
 * DESCBC加密
     *
     * @param src
     *            数据源
     * @param key
     *            密钥,长度必须是8的倍数
     * @return 返回加密后的数据
     * @throws Exception
     */
    public String encryptDESCBC(final String src, final String key) throws Exception {

        // --生成key,同时制定是des还是DESede,两者的key长度要求不同
        final DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
        final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        final SecretKey secretKey = keyFactory.generateSecret(desKeySpec);

        // --加密向量
        final IvParameterSpec iv = new IvParameterSpec(IV.getBytes("UTF-8"));

        // --通过Chipher执行加密得到的是一个byte的数组,Cipher.getInstance("DES")就是采用ECB模式,cipher.init(Cipher.ENCRYPT_MODE,
        // secretKey)就可以了.
        final Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
        final byte[] b = cipher.doFinal(src.getBytes("UTF-8"));

        // --通过base64,将加密数组转换成字符串
        final BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(b);
public String decryptDESCBC(final String src, final String key) throws Exception {
        // --通过base64,将字符串转成byte数组
        final BASE64Decoder decoder = new BASE64Decoder();
        final byte[] bytesrc = decoder.decodeBuffer(src);

        // --解密的key
        final DESKeySpec desKeySpec = new DESKeySpec(key.getBytes("UTF-8"));
        final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        final SecretKey secretKey = keyFactory.generateSecret(desKeySpec);

        // --向量
        final IvParameterSpec iv = new IvParameterSpec(IV.getBytes("UTF-8"));

        // --Chipher对象解密Cipher.getInstance("DES")就是采用ECB模式,cipher.init(Cipher.DECRYPT_MODE,
        // secretKey)就可以了.
        final Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
        final byte[] retByte = cipher.doFinal(bytesrc);

        return new String(retByte);

    }

    // 3DESECB加密,key必须是长度大于等于 3*8 = 24 位哈
    public String encryptThreeDESECB(final String src, final String key) throws Exception {
        final DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));
        final SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
        final SecretKey securekey = keyFactory.generateSecret(dks);

        final Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, securekey);
        final byte[] b = cipher.doFinal(src.getBytes());

        final BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(b).replaceAll("\r", "").replaceAll("\n", "");

 

RSAPublicKeySpec

  • 此类指定一个RSA公钥。

构造方法:

RSAPublicKeySpec(BigInteger modulus, BigInteger publicExponent)

创建一个新的RSAPublicKeySpec。

参数

modulus - 模数

publicExponent - 公众指数

 

  算法实现过程为:

 

        1. 随意选择两个大的质数p和q,p不等于q,计算N=pq。

        2. 根据欧拉函数,不大于N且与N互质的整数個数為(p-1)(q-1)。

        3. 选择一个整数e与(p-1)(q-1)互质,并且e小于(p-1)(q-1)。

        4. 用以下这个公式计算d:d× e ≡ 1 (mod (p-1)(q-1))。

        5. 将p和q的记录销毁。

 

        以上内容中,(N,e)是公钥,(N,d)是私钥

在上文讲到的RSA算法实现过程中提到(N,e)是公钥,(N,d)是私钥。既然已经获取到了PublicKey和PrivateKey了,那如何取到N、e、d这三个值呢。要取到这三个值,首先要将PublicKey和PrivateKey强制转换成RSAPublicKey和RSAPrivateKey。共同的N值可以通过getModulus()获取。执行RSAPublicKey.getPublicExponent()可以获取到公钥中的e值,执行RSAPrivateKey.getPrivateExponent()可以获取私钥中的d值。这三者返回类型都是BigInteger。代码如下:

由于程序中动态生成KeyPair对明文加密后生成的密文是不可测的,所以在实际开发中通常在生成一个KeyPair后将公钥和私钥的N、e、d这三个特征值记录下来,在真实的开发中使用这三个特征值再去将PublicKey和PrivateKey还原出来。还原方法如下:

 

// 使用N、e值还原公钥
02public static PublicKey getPublicKey(String modulus, String
03publicExponent)
04        throws NoSuchAlgorithmException, InvalidKeySpecException {
05    BigInteger bigIntModulus = new BigInteger(modulus);
06    BigInteger bigIntPrivateExponent = new BigInteger(publicExponent);
07    RSAPublicKeySpec keySpec = new RSAPublicKeySpec(bigIntModulus,
08bigIntPrivateExponent);
09    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
10    PublicKey publicKey = keyFactory.generatePublic(keySpec);
11    return publicKey;
12}
13 
14// 使用N、d值还原公钥
15public static PrivateKey getPrivateKey(String modulus, String
16privateExponent)
17        throws NoSuchAlgorithmException, InvalidKeySpecException {
18    BigInteger bigIntModulus = new BigInteger(modulus);
19    BigInteger bigIntPrivateExponent = new BigInteger(privateExponent);
20    RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(bigIntModulus,
21 bigIntPrivateExponent);
22    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
23    PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
24    return privateKey;
25}

 

        公钥和私钥都具备后,就可以使用加解密的工具类javax.crypto.Cipher对明文和密文进行处理了。与所有的引擎类一样,可以通过调用Cipher类中的getInstance(String transformation)静态工厂方法得到Cipher对象。该方法中的参数描述了由指定输入产生输出所进行的操作或操作集合,可以是下列两种形式之一:“algorithm/mode/padding”或“algorithm”。例如下面的例子就是有效的transformation形式:"DES/CBC/PKCS5Padding"或"DES"。如果没有指定模式或填充方式,就使用特定提供者指定的默认模式或默认填充方式。

 

        Cipher的加密和解密方式所调用的方法和过程都一样,只是传参不同的区别。如下代码:

1// 编码前设定编码方式及密钥
2cipher.init(mode, key);
3// 传入编码数据并返回编码结果
4byte[] dataResult = cipher.doFinal(input);

 

        Cipher.init(mode, key)方法中MODE指加密或解密模式,值为Cipher.ENCRYPT_MODE或Cipher.DECRYPT_MODE,参数key在加密时传入PublicKey,在解密时以PrivateKey传入。Cipher.doFinal(byte[] data)则是将待编码数据传入后并返回编码结果。为了将编码结果转为可读字符串,通常最后还使用BASE 64算法对最终的byte[]数据编码后显示给开发者。

RSA是目前最有影响力的公钥加密算法,该算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但那时想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥,即公钥,而两个大素数组合成私钥。公钥是可发布的供任何人使用,私钥则为自己所有,供解密之用。

 

        解密者拥有私钥,并且将由私钥计算生成的公钥发布给加密者。加密都使用公钥进行加密,并将密文发送到解密者,解密者用私钥解密将密文解码为明文

下面讲解RSA算法的应用。

 

        RSA的公钥和私钥是由KeyPairGenerator生成的,获取KeyPairGenerator的实例后还需要设置其密钥位数。设置密钥位数越高,加密过程越安全,一般使用1024位。如下代码:

 

[代码]java代码:

1KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA);
2// 密钥位数
3keyPairGen.initialize(1024);

 

        公钥和私钥可以通过KeyPairGenerator执行generateKeyPair()后生成密钥对KeyPair,通过KeyPair.getPublic()和KeyPair.getPrivate()来获取。如下代码:

 

[代码]java代码:

1// 动态生成密钥对,这是当前最耗时的操作,一般要2s以上。
2KeyPair keyPair = keyPairGen.generateKeyPair();
3// 公钥
4PublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
5// 私钥
6PrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
7byte[] publicKeyData = publicKey.getEncoded();
8byte[] privateKeyData = publicKey.getEncoded();

        公钥和私钥都有它们自己独特的比特编码,可以通过getEncoded()方法获取,返回类型为byte[]。通过byte[]可以再度将公钥或私钥还原出来。具体代码如下:

 

[代码]java代码:

01// 通过公钥byte[]将公钥还原,适用于RSA算法
02public static PublicKey getPublicKey(byte[] keyBytes) throws
03NoSuchAlgorithmException,InvalidKeySpecException {
04    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
05    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
06    PublicKey publicKey = keyFactory.generatePublic(keySpec);
07    return publicKey;
08}
09// 通过私钥byte[]将公钥还原,适用于RSA算法
10public static PrivateKey getPrivateKey(byte[] keyBytes) throws
11NoSuchAlgorithmException,InvalidKeySpecException {
12    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
13    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
14    PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
15    return privateKey;
16}

        在上文讲到的RSA算法实现过程中提到(N,e)是公钥,(N,d)是私钥。既然已经获取到了PublicKey和PrivateKey了,那如何取到N、e、d这三个值呢。要取到这三个值,首先要将PublicKey和PrivateKey强制转换成RSAPublicKey和RSAPrivateKey。共同的N值可以通过getModulus()获取。执行RSAPublicKey.getPublicExponent()可以获取到公钥中的e值,执行RSAPrivateKey.getPrivateExponent()可以获取私钥中的d值。这三者返回类型都是BigInteger

https://www.cnblogs.com/jukan/p/5524402.html

https://www.cnblogs.com/shindo/p/6021976.html

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中生成密码盐是为了增强密码的安全性,一般会将密码和盐值进行混合后再加密存储。以下是一种常见的Java密码盐生成方法: 1. 首先,生成一个随机的盐值字符串。可以使用Java的SecureRandom类生成一个安全的随机数作为盐。例如: ``` SecureRandom random = new SecureRandom(); byte[] saltBytes = new byte[16]; random.nextBytes(saltBytes); String salt = Base64.getEncoder().encodeToString(saltBytes); ``` 2. 将密码与盐值进行混合。可以使用Java的String类的concat方法将密码和盐值连接在一起。例如: ``` String password = "123456"; String saltedPassword = password.concat(salt); ``` 3. 对混合后的密码进行加密。常见的密码加密算法有MD5、SHA等。可以使用Java的MessageDigest类进行加密。例如: ``` MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] hashedBytes = digest.digest(saltedPassword.getBytes(StandardCharsets.UTF_8)); ``` 4. 将加密后的密码存储在数据库或其他持久化存储中,同时也要存储盐值。 在验证密码时,使用同样的盐值对用户输入的密码进行相同的操作,然后将结果与存储的加密后的密码进行比较。如果结果一致,则密码正确。 密码盐生成是一种增加密码安全性的方法,在存储和验证密码时都需要使用相同的盐值和加密算法。这样即使相同的密码在不同用户间被使用,也能得到不同的加密结果,提高了密码的安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值