目 录CONTENT

文章目录

java.security&org.bouncycastle - java安全

FatFish1
2024-12-16 / 0 评论 / 0 点赞 / 66 阅读 / 0 字 / 正在检测是否收录...

hash - 最简单的安全算法

com.google.common.hash包

支持多种加密哈希算法

加密/签名

加密算法包括:

  • 单向加密:单向加密又称为不可逆加密,在加密过程中不使用密钥,明文由系统加密处理成密文,密文无法解密,一般适合于验证。在验证过程中,重新输入明文,并经过同样的加密算法处理,得到相同的密文并被系统重新认证。算法有 MD5、SHA1、HMAC等。

  • 对称加密:也就是加密方和解密方利用同一个密钥对数据进行加密和解密,例如 DES、PBE 等等。

  • 非对称加密:非对称加密算法用到的密钥分为公钥和私钥,二者是非对称的。例如用公钥加密的内容需要使用私钥来解密,使用私钥加密的内容需要用公钥来解密。非对称加密算法有 DSA、RSA等

RSA算法

RSA非对称性密钥算法一般用于加密和签名:

  • 加密:因为我的请求对于对方来说是向所有人公开的,只有对方可以用独特的密钥解密,因此要加密。这就是所说的公钥加密,私钥解密

  • 签名:对方要验证我是我,因此我要用独特密钥加密,这就是所说的私钥加签,公钥解签

其中涉及两组四个密钥:A的公钥(PUB_A),A的私钥(PRI_A);B的公钥(PUB_B),B的私钥(PRI_B)

这时A向B发送信息的整个签名和加密的过程如下:

  1. A先用自己的私钥(PRI_A)对信息(一般是信息的摘要)进行签名。

  2. A接着使用B的公钥(PUB_B)对信息内容和签名信息进行加密。

这样当B接收到A的信息后,获取信息内容的步骤如下:

  1. 用自己的私钥(PRI_B)解密A用B的公钥(PUB_B)加密的内容;

  2. 得到解密后的明文后用A的公钥(PUB_A)解签A用A自己的私钥(PRI_A)的签名。

java.security包可以用于加密加签验证

RSA算法的典型应用 - ssh-keygen

可以使用ssh-keygen使用RSA算法生成ssh访问的秘钥

在gitbash(linux系统直接执行)执行:

ssh-keygen -t rsa
Enter file in which to save the key:敲回车
Enter passphrase (empty for no passphrase):输入自定义密码(需要记住)
Enter same passphrase again:输入刚才的自定义密码

/home/.ssh下id_rsa(私钥)和id_rsa.pub(公钥)

其中-t的作用是指定算法(默认RSA,可选DSA、ECDSA、ed25519、ECIES),也可以使用-b指定长度

默认算法可以通过以下指令查看:

ssh-keygen -l -f ~/.ssh/id_rsa
>> 2048 SHA256:IZZxAMiKdj+z4QvGxOQfWfkN5xwf/r4vjzFAPTgJTdQ reader@ansible (RSA)

即可看到默认长度为2048位,默认算法为RSA,或使用:

ssh-keygen -l -f ~/.ssh/id_rsa|awk '{print $4}'|awk -F'[()]+' '{print $2}'
>> RSA

java.security包

java.security框架是java提供的统一的框架用于规范安全加密,功能包括秘钥、摘要、签名,还提供了一些加密工具

对称性秘钥

KeyGenerator(javax.crypto 包下)用于生成对称密钥。

支持算法:AES、ARCFOUR、DES、DESede、HmacMD5、HmacSHA1、HmacSHA224、HmacSHA256、HmacSHA384、HmacSHA512、RC2 等。

public static final KeyGenerator getInstance(String algorithm, String provider)
public static final KeyGenerator getInstance(String algorithm)
public final void init(int keysize)
public final void init(int keysize, SecureRandom random)
public final void init(SecureRandom random)
public final void init(AlgorithmParameterSpec params, SecureRandom random)
public final SecretKey generateKey()

示例如下:

public static void main(String[] args) throws Exception {
        KeyGenerator kg = KeyGenerator.getInstance("DES");
        SecureRandom random = new SecureRandom();
        random.nextBytes(new byte[128]);
        kg.init(56, random);
        SecretKey sk = kg.generateKey();
        byte[] b = sk.getEncoded();
        System.out.println(new String(Base64.encodeBase64(b)));  // XZdrC/in5uk=
    }

非对称性秘钥

KeyPairGenerator(java.security 包下) 用于生成非对称加密算法的密钥对 KeyPair(java.security 包下),KeyPair 会包括一个公钥和私钥。

支持算法:DiffieHellman、DSA、RSA、RSASSA-PSS、EC 等。

KeyPairGenerator.java 和 KeyPair.java 类中的重要的方法如下所示:

// KeyPairGenerator.java
public static KeyPairGenerator getInstance(String algorithm)
public static KeyPairGenerator getInstance(String algorithm, String provider)
public void initialize(int keysize, SecureRandom random)
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
public final KeyPair genKeyPair() 
// KeyPair.java
public PublicKey getPublic()
public PrivateKey getPrivate()

示例如下:

	public static void main(String[] args) throws Exception {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        SecureRandom random = new SecureRandom();
        random.nextBytes(new byte[516]);
        keyGen.initialize(516, random);
        KeyPair keyPair = keyGen.genKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        PrivateKey privateKey = keyPair.getPrivate();
        byte[] publicKeyEncoded = publicKey.getEncoded();
        byte[] privateKeyEncoded = privateKey.getEncoded();
        System.out.println(new String(Base64.encodeBase64(publicKeyEncoded)));
        System.out.println(new String(Base64.encodeBase64(privateKeyEncoded)));
    }

秘钥和秘钥规格的转化

KeySpec 是一个接口,用来组成密钥内容的规范。如果密钥存储在硬件设备上,则其规范可以包含有助于标识该设备上的密钥的信息。

KeySpec 具有规范性,所以一般会根据外部参数生成 KeySpec,再根据 KeySpec 生成对应的 KeySecretKeyFactory、KeyFactory 的作用就是转换 Key 与 KeySpec

SecretKeyFactory 用于对称加密的密钥和密钥规格之间的转换,配合 KeyGenerator 使用,支持算法:AES、ARCFOUR、DES、DESede、PBEWithMD5AndDES、PBEWithHmacSHA256AndAES_128、PBKDF2WithHmacSHA256 等。

SecretKeyFactory.java 中的几个方法如下所示。

public static final SecretKeyFactory getInstance(String algorithm)
public static final SecretKeyFactory getInstance(String algorithm, String provider)
public final SecretKey translateKey(SecretKey key)
public final SecretKey generateSecret(KeySpec keySpec)
public final KeySpec getKeySpec(SecretKey key, Class<?> keySpec)

示例如下:

	public static void main(String[] args) throws Exception {
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        byte[] desKey = "hello world".getBytes(StandardCharsets.UTF_8); // 设置密钥
        DESKeySpec keySpec = new DESKeySpec(desKey);                    // 设置密钥参数
        SecretKey key = keyFactory.generateSecret(keySpec);             // 得到密钥对象
        byte[] b = key.getEncoded();
        System.out.println(new String(Base64.encodeBase64(b)));         // aGRtbW5XV1c=
    }

KeyFactory 用于非对称加密的密钥和密钥规格之间的转换,配合 KeyPairGenerator 使用,支持算法:DiffieHellman、DSA、RSA、RSASSA-PSS、EC 等。

KeyFactory.java 中的几个方法如下所示。

// KeyFactory.java
public static KeyFactory getInstance(String algorithm)
public static KeyFactory getInstance(String algorithm, String provider)
public final PublicKey generatePublic(KeySpec keySpec)
public final PrivateKey generatePrivate(KeySpec keySpec)
public final <T extends KeySpec> T getKeySpec(Key key, Class<T> keySpec)

摘要算法

摘要算法是一种单向的加密算法,例如MD5、SHA、MAC。

MD5、SHA 会根据明文用哈希算法计算一个固定长度的摘要(哈希值),然后把明文和摘要发送给接收者,接收者根据同样的算法计算出摘要,对比两个摘要是否一样即可验证明文的正确性。它的应用场景是防止报文被篡改和校验数据。

工具包括MessageDigest 和 javax.crypto.Mac(HMAC)

签名算法

签名一般是指用非对称加密算法的私钥来加密明文的过程,生成的密文可以被持有公钥的人识别解密,只要你的公钥是准确无误的,就能保证你解密的数据是来自持有私钥的一方。

工具包括Signature,配合 KeyPairGenerator 使用

Cipher - 常用加密工具类

用于加密/解密数据。支持各种类型的算法:对称加密(例如 AES),非对称加密(例如RSA)。

   <dependency>
   	<groupId>org.bouncycastle</groupId>
       <artifactId>bcprov-jdk15on</artifactId>
       <version>...</version>
   </dependency>

boucycastle的bcpkix是专门用于处理加解密的,例如org.bouncycastle.openssl是专门用于处理openssl的PEM文件即私钥和私钥密码

java.security开发实例

需求一、基于国密SM2SignWithSM3算法实现签名校验(正确性目前有待验证)

国密算法是国家密码局认定的国产密码算法。主要有SM1,SM2,SM3,SM4。密钥长度和分组长度均为128位

其中SM2、SM3、SM4是商用算法

  • SM2是基于椭圆曲线的公钥密码算法,包括用于数字签名的SM2-1、用于密钥交换的SM2-2和用于公钥密码的SM2-3,可以理解为SM2是过程的RSA

  • SM3是能够计算出256比特的散列值的单向散列函数,主要用于数字签名和消息认证码。可以理解为SM3是国产的MD5算法

  • SM4是属于对称密码的一种分组密码算法,分组长度和密钥长度均为128比特。可以理解为SM4是国产的AES算法

使用SM2SignWithSM3实际上就是先用SM2生成公私钥对加密,然后加签

public static void main(String[] args) throws Exception {
    String data = "Hello World";
    // 基于SM2生成非对称秘钥对
    ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
    keyPairGenerator.initialize(sm2Spec, new SecureRandom());
    KeyPair keyPair = keyPairGenerator.generateKeyPair();
    PrivateKey privateKey = keyPair.getPrivate();
    PublicKey publicKey = keyPair.getPublic();
    // 基于SM3withSM2签名
    Signature signature = Signature.getInstance("SM3withSM2");
    signature.initSign(privateKey);
    signature.update(data.getBytes());
    byte[] sign = signature.sign();
    // 使用公钥对签名进行验签
    Signature signature2 = Signature.getInstance("SM3withSM2");
    signature2.initVerify(publicKey);
    signature2.update(data.getBytes());
    System.out.println(signature2.verify(sign));
}

因为原生的java.security不支持SM2算法,必须基于BouncyCastleProvider基于sm2p256v1算法生成秘钥规范,这是一个椭圆曲线

0

评论区