再聊对称加密、非对称加密(Kotlin)

  • 对称加密

发送方和接收方 用同一个秘钥对数据加密解密

例:
A和B约定好秘钥"123456"(比如客户端和服务端)

A给B发消息:"我喜欢你"

A用 "123456"“我喜欢你” 加密得到结果 “乱码”,把 “乱码” 发给B
B用 "123456"“乱码” 解密得到结果 "我喜欢你"

对称加密的代表算法有DES,AES等,这里只看DES,AES

DES:数据加密算法(Data Encryption Algorithm,缩写DEA):
运算速度快,资源消耗较少,安全性低

AES:高级加密标准(英语:Advanced Encryption Standard,缩写AES):
这个标准用来替代原先的DES,运算速度快,安全性高,资源消耗少

代码示例:
package com.i.cipher

import android.util.Base64
import java.security.*
import javax.crypto.Cipher
import javax.crypto.KeyGenerator
import javax.crypto.SecretKeyFactory
import javax.crypto.spec.DESKeySpec
import javax.crypto.spec.SecretKeySpec

//---------------------------------DES-----------------------------------

fun desEnc(input: String, password: String): String {
    val cipher = Cipher.getInstance("DES")
    val secretKey = SecretKeyFactory.getInstance("DES")
    val keySpec = DESKeySpec(password.toByteArray())
    val key: Key = secretKey.generateSecret(keySpec)
    cipher.init(Cipher.ENCRYPT_MODE, key)
    val encrypt = cipher.doFinal(input.toByteArray())
    return Base64.encodeToString(encrypt, Base64.NO_WRAP)
}

fun desDec(input: String, password: String): String {
    val cipher = Cipher.getInstance("DES")
    val secretKey = SecretKeyFactory.getInstance("DES")
    val keySpec = DESKeySpec(password.toByteArray())
    val key: Key = secretKey.generateSecret(keySpec)
    cipher.init(Cipher.DECRYPT_MODE, key)
    val encrypt = cipher.doFinal(Base64.decode(input, Base64.NO_WRAP))
    return String(encrypt)
}

//---------------------------------AES-----------------------------------

fun aesEnc(input: String, password: String): String {
    val cipher = Cipher.getInstance("AES")
    val keySpec = SecretKeySpec(password.toByteArray(), "AES")
    cipher.init(Cipher.ENCRYPT_MODE, keySpec)
    val encrypt = cipher.doFinal(input.toByteArray())
    return Base64.encodeToString(encrypt, Base64.NO_WRAP)
}

fun aesDec(input: String, password: String): String {
    val cipher = Cipher.getInstance("AES")
    val keySpec = SecretKeySpec(password.toByteArray(), "AES")
    cipher.init(Cipher.DECRYPT_MODE, keySpec)
    val encrypt = cipher.doFinal(Base64.decode(input, Base64.NO_WRAP))
    return String(encrypt)
}
//---------------------------------AES(keyGenerator)推荐-----------------------------------

fun createKey(password: String): Key {
    val keyGenerator = KeyGenerator.getInstance("AES")
    keyGenerator.init(128, SecureRandom(password.toByteArray()))
    return keyGenerator.generateKey()
}

fun encode(key: Key, input: String): String {
    val cipher = Cipher.getInstance("AES")
    cipher.init(Cipher.ENCRYPT_MODE, key)
    val dataByte = cipher.doFinal(input.toByteArray())
    val encodeByte = Base64.encodeToString(dataByte, Base64.NO_WRAP)
    return encodeByte
}

fun decode(key: Key, input: String): String {
    val decodeByte = Base64.decode(input.toByteArray(), Base64.NO_WRAP)
    val cipher = Cipher.getInstance("AES")
    cipher.init(Cipher.DECRYPT_MODE, key)
    val dataByte = cipher.doFinal(decodeByte)
    return String(dataByte)
}

测试代码

		//base64的基本加解密
        btn_base64.setOnClickListener {
            val input = "今天天气啦啦啦"
            tv_before.setText("加密前:" + input)
            val encode = Base64.encodeToString(input.toByteArray(), Base64.NO_WRAP);
            tv_after.setText("加密后:" + encode)
            val decode = String(Base64.decode(encode, Base64.NO_WRAP))
            tv_dec_after.setText("解密后:" + decode)
        }
        btn_des.setOnClickListener {
            val input = "今天天气不错"
            //8位密码
            val password = "12345678"
            tv_before.setText("加密前:" + input)

            val encrypt = desEnc(input, password)
            tv_after.setText("加密后:" + encrypt)

            val decrypt = desDec(encrypt, password)
            tv_dec_after.setText("解密后:" + decrypt)
        }
        btn_aes.setOnClickListener {
            val input = "今天天气还行"
            //16位密码
            val password = "1234567812345678"
            tv_before.setText("加密前:" + input)

            val encrypt = aesEnc(input, password)
            tv_after.setText("加密后:" + encrypt)

            val decrypt = aesDec(encrypt, password)
            tv_dec_after.setText("解密后:" + decrypt)

        }
        btn_aes_keyGenerator.setOnClickListener {
            val input = "今天天气太好了"
            val password = "123456abc"
            tv_before.setText("加密前:" + input)
            val createKey = createKey(password)
            val encode = encode(createKey, input)
            tv_after.setText("加密后:" + encode)
            val decode = decode(createKey, encode)
            tv_dec_after.setText("解密后:" + decode)

        }
  • 非对称加密

发送方用接收方的公钥加密,接收方用自己的私钥解密

例:
A生成"APrikey","APubkey"
B生成"BPrikey","BPubkey"

A给B发消息:"我喜欢你"

A用 "BPubkey"“我喜欢你” 加密得到结果 “乱码”,把 “乱码” 发给B
B用 "BPrikey"“乱码” 解密得到结果 "我喜欢你"

B给A发消息同理

//---------------------------------RSA-----------------------------------

fun createKeyPair(): KeyPair {
    val generator = KeyPairGenerator.getInstance("RSA")
    return generator.genKeyPair()
}

/**
 * 私钥加密
 */
fun encByPrivateKey(input: String, privateKey: PrivateKey): String {
    val cipher = Cipher.getInstance("RSA")
    cipher.init(Cipher.ENCRYPT_MODE, privateKey)
    val encrypt = cipher.doFinal(input.toByteArray())
    return Base64.encodeToString(encrypt, Base64.NO_WRAP)
}

/**
 * 公钥解密
 */
fun decByPublicKey(input: String, publicKey: PublicKey): String {
    val decode = Base64.decode(input, Base64.NO_WRAP)
    val cipher = Cipher.getInstance("RSA")
    cipher.init(Cipher.DECRYPT_MODE, publicKey)
    val encrypt = cipher.doFinal(decode)
    return String(encrypt)
}

/**
 * 公钥加密
 */
fun encByPublicKey(input: String, publicKey: PublicKey): String {
    val cipher = Cipher.getInstance("RSA")
    cipher.init(Cipher.ENCRYPT_MODE, publicKey)
    val encrypt = cipher.doFinal(input.toByteArray())
    return Base64.encodeToString(encrypt, Base64.NO_WRAP)
}

/**
 * 私钥解密
 */
fun decByPrivateKey(input: String, privateKey: PrivateKey): String {
    val decode = Base64.decode(input, Base64.NO_WRAP)
    val cipher = Cipher.getInstance("RSA")
    cipher.init(Cipher.DECRYPT_MODE, privateKey)
    val encrypt = cipher.doFinal(decode)
    return String(encrypt)
}

测试代码

    //私钥加密,公钥解密
    fun priTopub() {
        val input = "今天天气真好啊"
        tv_before.setText("加密前:" + input)
        val keyPair = createKeyPair()
        val encByPrivateKey = encByPrivateKey(input, keyPair.private)
        tv_after.setText("加密后:" + encByPrivateKey)
        val decByPublicKey = decByPublicKey(encByPrivateKey, keyPair.public)
        tv_dec_after.setText("解密后:" + decByPublicKey)
    }

    //公钥加密,私钥解密
    fun pubTopri() {
        val input = "今天天气非常好啊"
        tv_before.setText("加密前:" + input)
        val keyPair = createKeyPair()
        val encByPublicKey = encByPublicKey(input, keyPair.public)
        tv_after.setText("加密后:" + encByPublicKey)
        val decByPrivateKey = decByPrivateKey(encByPublicKey, keyPair.private)
        tv_dec_after.setText("解密后:" + decByPrivateKey)
    }

参考:
https://zhuanlan.zhihu.com/p/49494990
https://blog.csdn.net/u011109931/article/details/79466587
https://blog.csdn.net/hongxue8888/article/details/103850353
源码:https://gitee.com/zzgits/Cipher
百度百科:https://baike.baidu.com/item/%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95/1208652?fr=aladdin
1.A要向B发送信息,A和B都要产生一对用于加密和解密的公钥和私钥。
2.A的私钥保密,A的公钥告诉B;B的私钥保密,B的公钥告诉A。
3.A要给B发送信息时,A用B的公钥加密信息,因为A知道B的公钥。
4.A将这个消息发给B(已经用B的公钥加密消息)。
5.B收到这个消息后,B用自己的私钥解密A的消息。其他所有收到这个报文的人都无法解密,因为只有B才有B的私钥。

拓展:

HTTPS原理

对称加密速度快,不安全
非对称安全,传输数据小
那怎么办呢?怎么做到又安全,传输的数据又多呢?
答案:用对称加密传输数据,用非对称加密只加密对称加密生成的秘钥(秘钥数据小)
保证了对称加密的秘钥的安全了,那么传输数据自然就安全了。

客户端服务端交互 场景:

客户端: 我要发起HTTPS请求,麻烦给我一个非对称加密的公钥;
服务器: (生成一对非对称加密的密钥对,然后把公钥发给客户端),接着,这是公钥;
客户端:收到公钥并用公钥对对称秘钥加密
服务器:收到对称秘钥后,用自己的私钥解密
现在,客户端和服务器都知道了这把密钥,就能愉快地用这个密钥对称加密数据…

此时有一个坏人:
坏人: 在客户端向服务器申请公钥的时候,劫持服务器返回的A公钥,然后自己生成一个新的公钥返回给客户端。
客户端:收到公钥并用公钥对对称秘钥加密
坏人:直接就拿到了对称秘钥
为了骗服务端,坏人又使用A公钥加密发给服务器。
这里是说客户端收到了假公钥,那如果客户端那边把公钥写死在代码里面,这个问题是否就不存在了呢?
答案:否,坏人可以通过其他方式拿到A公钥,然后自己生成一个新的对称秘钥返回给服务端。
服务端以为这个新的对称秘钥就是客户端给他的。
原文请看:https://www.jianshu.com/p/ca7df01a9041

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

哆啦A梦z

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

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

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

打赏作者

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

抵扣说明:

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

余额充值