Java 加密算法(二)

个人博客:haichenyi.com。感谢关注

补充知识点:

密钥: 加密方用公钥,解密方用私钥

重要的事情强调六遍:

不用自己写加密算法

不用自己写加密算法

不用自己写加密算法

不用自己写加密算法

不用自己写加密算法

不用自己写加密算法

Cipher类

  Android有专门用来加密的工具类Cipher类,他里面封装了几种常用的加密算法,本篇介绍两种AES,RSA。

用法

分三步:以AES举例说明

  /**
   * 加密方式:AES
   * 工作模式:ECB,CBC,CTR,OFB,CFB
   * 填充模式:PKCS5Padding,PKCS7Padding,ZEROPadding等等
   */
String CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";//AES是加密方式 CBC是工作模式 PKCS5Padding是填充模式


//第一步:获取对象
Cipher cipher = Cipher.getInstance(String transformation);//传 CBC_PKCS5_PADDING


//第二步:设置初始化参数
    /**
     * 第一个参数:传类型,是加密Cipher.ENCRYPT_MODE,还是解密Cipher.DECRYPT_MODE
     * 第二个参数:传密钥key,我们这里传的是SecretKeySpec,它实现SecretKey,SecretKey实现Key接口。
     *             SecretKeySpec keySpec = new SecretKeySpec(raw, AES);//第一个参数传密钥byte数组,第二个参数传加密类型也就是"AES"字符串即可
     * 第三个参数:传偏移量AlgorithmParameterSpec,我们这里传的IvParameterSpec,他实现AlgorithmParameterSpec接口,iv偏移量传默认的16个0的字节数组
     *              new IvParameterSpec(new byte[cipher.getBlockSize()]),这里是传的默认的16个0的byte数组,也是常用的方式
     */
cipher.init(int opmode, Key key, AlgorithmParameterSpec params)


第三步:加密。传需要加密的字符串的byte数组
cipher.doFinal(byte[] input)

经过以上三步:AES加密就算完成了,加密之后就需要解密,辣么,怎么解密呢?

    草鸡简单,第二步初始化的时候,第一个参数传解密即可,其他都是一样的。

对称加密

概念

出自百度百科

  需要对加密和解密使用相同密钥的加密算法。由于其速度快,对称性加密通常在消息发送方需要加密大量数据时使用。对称性加密也称为密钥加密。

  所谓对称,就是采用这种加密方法的双方使用方式用同样的密钥进行加密和解密。密钥是控制加密及解密过程的指令。算法是一组规则,规定如何进行加密和解密。

  因此,加密的安全性不仅取决于加密算法本身,密钥管理的安全性更是重要。因为加密和解密都使用同一个密钥,如何把密钥安全地传递到解密者手上就成了必须要解决的问题。

  说了这么多废话,要我说,就一句话公钥,私钥 相同 的加密方式称之为对称加密

用法——AES

  申明:我这里并不是说对称加密就只有AES这一种方式,相反,对称加密有很多种,我这里只讲我用到的对称加密中的一种方式——AES


  private static final String CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";//AES是加密方式 CBC是工作模式 PKCS5Padding是填充模式
  private static final String AES = "AES";//AES 加密
  private static final String SHA1PRNG = "SHA1PRNG";// SHA1PRNG 强随机种子算法, 要区别4.2以上版本的调用方法

/**
   * 随机生成密钥,传同一个字符串,每次都生成的不一样
   * @param seed 一般传用户的密码
   * @return 返回密钥的byte数组
   * @throws Exception 异常
   */
  private static byte[] getRawKey(String seed) throws Exception {
    SecureRandom sr = null;
    // 在4.2以上版本中,SecureRandom获取方式发生了改变
    if (android.os.Build.VERSION.SDK_INT >= 17) {
      sr = SecureRandom.getInstance(SHA1PRNG, "Crypto");
    } else {
      sr = SecureRandom.getInstance("SHA1PRNG"); // 获得一个随机数,传入的参数为默认方式。
    }
    sr.setSeed(seed.getBytes());  // 设置一个种子,这个种子一般是用户设定的密码。也可以是其它某个固定的字符串
    KeyGenerator keyGen = KeyGenerator.getInstance("AES");  // 获得一个key生成器(AES加密模式)
    //AES中128位密钥版本有10个加密循环,192比特密钥版本有12个加密循环,256比特密钥版本则有14个加密循环。
    keyGen.init(128, sr);      // 设置密匙长度128位
    SecretKey key = keyGen.generateKey();  // 获得密匙
    return key.getEncoded();
  }


  /**
   * 加密过程
   * @param raw 密钥的数组
   * @param clear 需要加密的byte数组
   * @return 加密后的byte数组
   * @throws Exception 异常
   */
  private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
    SecretKeySpec keySpec = new SecretKeySpec(raw, AES);
    Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING);
    //iv偏移量传默认的16个0的字节数组
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
    return cipher.doFinal(clear);
  }


  /*
   * 解密
   */
  private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
    SecretKeySpec keySpec = new SecretKeySpec(raw, AES);
    Cipher cipher = Cipher.getInstance(CBC_PKCS5_PADDING);
    cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(new byte[cipher.getBlockSize()]));
    return cipher.doFinal(encrypted);
  }

  上面给的三个方法,一个获取密钥,一个加密,一个解密,注释写的很清楚,我就不用再讲了,转16进制的方法,我前一篇讲加密的时候就给出来了,不知道的可以去前一篇看一下,我下面给出调用方式和结果截图

   try {
          byte[] rawKey = getRawKey(key);
          Log.v("wz", rawKey.length + "");
          String s = bytesToHexFun1(rawKey);
          Log.v("wz","密钥16进制-->"+s);
          byte[] encrypt = encrypt(rawKey, data.getBytes());
          String after = Base64.encodeToString(encrypt, Base64.NO_WRAP);
          Log.v("wz","加密后-->"+after);
          byte[] decode = Base64.decode(after, Base64.NO_WRAP);
          byte[] before = decrypt(rawKey, decode);
          Log.v("wz","解密后-->"+new String(before));
        } catch (Exception e) {
          e.printStackTrace();
        }

结果:

非对称加密

概念

出自百度百科

  1976年,美国学者Dime和Henman为解决信息公开传送和密钥管理问题,提出一种新的密钥交换协议,允许在不安全的媒体上的通讯双方交换信息,安全地达成一致的密钥,这就是“公开密钥系统”。

  与对称加密算法不同,非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法。

  说了这么多废话,要我说,就一句话公钥,私钥 不相同 的加密方式称之为对称加密

用法——RSA

  申明:我这里并不是说非对称加密就只有RSA这一种方式,相反,对非称加密有很多种,我这里只讲我用到的非对称加密中的一种方式——RSA

  辣么,成对公钥,私钥怎么来呢?难道我们自己去写吗?你要是会写,那你很棒棒哦,反正我不会(爱咋咋),我是在线生成公钥,私钥对。用法跟上面讲的AES是类似的:

/**
   * 我们之前拿到的是公钥,我们还要把公钥转成Key
   * 因为cipher.init()初始化的时候,第二个参数需要传Key类型的,并不是String
   * 获取Key,我这里返回的是PublicKey,它实现的Key接口
   * @param pubKey 生成的公钥
   * @return 最后需要的key
   * @throws Exception 异常
   */
  public static PublicKey loadPublicKey(String pubKey) throws Exception {
    byte[] buffer = Base64.decode(pubKey, Base64.DEFAULT);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
    return keyFactory.generatePublic(keySpec);
  }

  /**
   * 加密
   * @param data 需要加密的数据
   * @param publicKey key
   * @return 返回加密后的byte,需要转成字符串
   * @throws Exception 异常
   */
  private static byte[] encryptRSA(String data,PublicKey publicKey) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.ENCRYPT_MODE,publicKey);
    return cipher.doFinal(data.getBytes());
  }

  /**
   * 解密(我们需要注意的是,我们解密的是私钥加密的数据,不能解密公钥加密的数据)
   * @param data 需要解密的数据
   * @param publicKey key
   * @return 返回解密后的数组
   * @throws Exception 异常
   */
  private static byte[] decryptRSA(String data,PublicKey publicKey) throws Exception {
    Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(Cipher.DECRYPT_MODE,publicKey);
    return cipher.doFinal(data.getBytes());
  }

  这里,注释说的很清楚,看懂了前面的AES,辣么,这个RSA应该不是问题。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
自写Java加密算法可能需要使用Java Cryptography Architecture (JCA) 提供的一系列类来实现。JCA定义了一些常用的密码学算法框架,如Cipher、MessageDigest、MAC、Signature等,可以用于实现各种加密、哈希、认证码和数字签名等算法。 要自写Java加密算法,您可以使用JCA提供的Cipher类。Cipher类提供了加密和解密的功能,可以使用不同的算法和模式进行加密,如对称加密算法、非对称加密算法、哈希函数等。您可以自定义算法和密钥来实现自己的加密算法。 首先,您需要选择合适的加密算法和模式。对称加密算法常见的有AES、DES、3DES等,非对称加密算法常见的有RSA、DSA等。然后,您需要使用Cipher类进行初始化,指定算法和模式,并传入密钥。接下来,您可以使用Cipher类的encrypt方法对数据进行加密,使用decrypt方法进行解密。 在自写加密算法时,需要注意安全性和效率。要确保加密算法的安全性,可以选择已经经过广泛测试和认可的算法。同时,为了提高效率,可以优化算法的实现方式,如使用合适的数据结构和算法细节优化。 使用JCA实现自己的加密算法有一些挑战和注意事项。首先,要了解JCA的使用方法和相关概念,熟悉各种算法的特性和适用场景。其次,要确保代码的可靠性和安全性,避免常见的安全漏洞和攻击。 总结起来,要自写Java加密算法,您可以使用JCA提供的类和接口,在此框架中定义和实现自己的算法。首先选择合适的加密算法和模式,然后使用Cipher类进行初始化并传入密钥,最后使用encrypt和decrypt方法进行加密和解密操作。但在实现时,需注意安全性和效率,并遵循相关的安全编码规范。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Java实现7种常见密码算法](https://blog.csdn.net/fm18771120556/article/details/127460019)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海晨忆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值