简介

加解密现状,编写此项目的背景:

  • 需要考虑系统环境兼容性问题(Linux、Windows)
  • 语言互通问题(如C#、Java)
  • 网上资料版本不一、不全面
  • .NET官方库密码算法提供不全面,很难针对其他语言(Java)进行适配

本系列文章主要介绍如何结合BouncyCastle在 .NET Core 中使用非对称加密算法、编码算法、哈希算法、对称加密算法、国密算法等一系列算法,内容篇幅代码居多(加解密算法相关的原理知识网上有很多,因此不过多介绍)。如有错误之处,还请大家批评指正。

本系列代码项目地址:https://github.com/fuluteam/ICH.BouncyCastle.git

功能依赖

BouncyCastle(https://www.bouncycastle.org/csharp) 是一个开放源码的轻量级密码术包;它支持大量的密码术算法,它提供了很多.NET Core标准库没有的算法。

支持.NET 4,.NET Standard 1.0-2.0,WP,Silverlight,MonoAndroid,Xamarin.iOS,.NET Core

功能 依赖
Portable.BouncyCastle Portable.BouncyCastle • 1.8.5

生成RSA秘钥

PKCS1格式

/// <summary>
/// PKCS1(非Java适用)
/// </summary>
/// <param name="keySize">密钥长度”一般只是指模值的位长度。目前主流可选值:1024、2048、3072、4096...</param>
/// <param name="format">PEM格式</param>
/// <returns></returns>
public RSAKeyParameter Pkcs1(int keySize, bool format=false)
{
var keyGenerator = GeneratorUtilities.GetKeyPairGenerator("RSA");
keyGenerator.Init(new KeyGenerationParameters(new SecureRandom(), keySize)); var keyPair = keyGenerator.GenerateKeyPair(); var subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public);
var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private); if (!format)
{
return new RSAKeyParameter
{
PrivateKey = Base64.ToBase64String(privateKeyInfo.ParsePrivateKey().GetEncoded()),
PublicKey = Base64.ToBase64String(subjectPublicKeyInfo.GetEncoded())
};
} var rsaKey = new RSAKeyParameter();
using (var sw = new StringWriter())
{
var pWrt = new PemWriter(sw);
pWrt.WriteObject(keyPair.Private);
pWrt.Writer.Close();
rsaKey.PrivateKey = sw.ToString();
} using (var sw = new StringWriter())
{
var pWrt = new PemWriter(sw);
pWrt.WriteObject(keyPair.Public);
pWrt.Writer.Close();
rsaKey.PublicKey = sw.ToString();
} return rsaKey;
}

PKCS8格式

/// <summary>
/// PKCS8(JAVA适用)
/// </summary>
/// <param name="keySize">密钥长度”一般只是指模值的位长度。目前主流可选值:1024、2048、3072、4096...</param>
/// <param name="format">PEM格式</param>
/// <returns></returns>
public RSAKeyParameter Pkcs8(int keySize, bool format=false)
{
var keyGenerator = GeneratorUtilities.GetKeyPairGenerator("RSA");
keyGenerator.Init(new KeyGenerationParameters(new SecureRandom(), keySize));
var keyPair = keyGenerator.GenerateKeyPair(); var subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public);
var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private); if (!format)
{
return new RSAKeyParameter
{
PrivateKey = Base64.ToBase64String(privateKeyInfo.GetEncoded()),
PublicKey = Base64.ToBase64String(subjectPublicKeyInfo.GetEncoded())
};
} var rsaKey = new RSAKeyParameter();
using (var sw = new StringWriter())
{
var pWrt = new PemWriter(sw);
var pkcs8 = new Pkcs8Generator(keyPair.Private);
pWrt.WriteObject(pkcs8);
pWrt.Writer.Close();
rsaKey.PrivateKey = sw.ToString();
} using (var sw = new StringWriter())
{
var pWrt = new PemWriter(sw);
pWrt.WriteObject(keyPair.Public);
pWrt.Writer.Close();
rsaKey.PublicKey = sw.ToString();
} return rsaKey;
}

私钥操作

PKCS1与PKCS8格式互转

仅私钥有PKCS1和PKCS8之分,公钥无格式区别。

 /// <summary>
/// Pkcs1>>Pkcs8
/// </summary>
/// <param name="privateKey">Pkcs1私钥</param>
/// <param name="format">是否转PEM格式</param>
/// <returns></returns>
public static string PrivateKeyPkcs1ToPkcs8(string privateKey, bool format = false)
{
var akp = RSAUtilities.GetAsymmetricKeyParameterFormPrivateKey(privateKey);
if (format)
{
var sw = new StringWriter();
var pWrt = new PemWriter(sw);
var pkcs8 = new Pkcs8Generator(akp);
pWrt.WriteObject(pkcs8);
pWrt.Writer.Close();
return sw.ToString();
}
else
{
var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp);
return Base64.ToBase64String(privateKeyInfo.GetEncoded());
}
}
/// <summary>
/// Pkcs8>>Pkcs1
/// </summary>
/// <param name="privateKey">Pkcs8私钥</param>
/// <param name="format">是否转PEM格式</param>
/// <returns></returns>
public static string PrivateKeyPkcs8ToPkcs1(string privateKey, bool format = false)
{
var akp = RSAUtilities.GetAsymmetricKeyParameterFormAsn1PrivateKey(privateKey);
if (format)
{
var sw = new StringWriter();
var pWrt = new PemWriter(sw);
pWrt.WriteObject(akp);
pWrt.Writer.Close();
return sw.ToString();
}
else
{
var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp);
return Base64.ToBase64String(privateKeyInfo.ParsePrivateKey().GetEncoded());
}
}

PKCS1与PKCS8私钥中提取公钥

/// <summary>
/// 从Pkcs1私钥中提取公钥
/// </summary>
/// <param name="privateKey">Pkcs1私钥</param>
/// <returns></returns>
public static string GetPublicKeyFromPrivateKeyPkcs1(string privateKey)
{
var instance = RsaPrivateKeyStructure.GetInstance(Base64.Decode(privateKey)); var publicParameter = (AsymmetricKeyParameter)new RsaKeyParameters(false, instance.Modulus,instance.PublicExponent); var privateParameter = (AsymmetricKeyParameter)new RsaPrivateCrtKeyParameters(instance.Modulus,instance.PublicExponent, instance.PrivateExponent, instance.Prime1, instance.Prime2, instance.Exponent1,instance.Exponent2, instance.Coefficient); var keyPair = new AsymmetricCipherKeyPair(publicParameter, privateParameter);
var subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public); return Base64.ToBase64String(subjectPublicKeyInfo.GetEncoded());
}
/// <summary>
/// 从Pkcs8私钥中提取公钥
/// </summary>
/// <param name="privateKey">Pkcs8私钥</param>
/// <returns></returns>
public static string GetPublicKeyFromPrivateKeyPkcs8(string privateKey)
{
var privateKeyInfo = PrivateKeyInfo.GetInstance(Asn1Object.FromByteArray(Base64.Decode(privateKey)));
privateKey = Base64.ToBase64String(privateKeyInfo.ParsePrivateKey().GetEncoded()); var instance = RsaPrivateKeyStructure.GetInstance(Base64.Decode(privateKey)); var publicParameter = (AsymmetricKeyParameter)new RsaKeyParameters(false, instance.Modulus,instance.PublicExponent); var privateParameter = (AsymmetricKeyParameter)new RsaPrivateCrtKeyParameters(instance.Modulus,instance.PublicExponent, instance.PrivateExponent, instance.Prime1, instance.Prime2, instance.Exponent1,instance.Exponent2, instance.Coefficient); var keyPair = new AsymmetricCipherKeyPair(publicParameter, privateParameter);
var subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public); return Base64.ToBase64String(subjectPublicKeyInfo.GetEncoded());
}

PEM操作

PEM格式密钥读取

public static string ReadPkcs1PrivateKey(string text)
{
if (!text.StartsWith("-----BEGIN RSA PRIVATE KEY-----"))
{
return text;
} using (var reader = new StringReader(text))
{
var pr = new PemReader(reader);
var keyPair = pr.ReadObject() as AsymmetricCipherKeyPair;
pr.Reader.Close(); var privateKeyInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair?.Private);
return Base64.ToBase64String(privateKeyInfo.ParsePrivateKey().GetEncoded());
}
} public static string ReadPkcs8PrivateKey(string text)
{
if (!text.StartsWith("-----BEGIN PRIVATE KEY-----"))
{
return text;
} using (var reader = new StringReader(text))
{
var pr = new PemReader(reader);
var akp = pr.ReadObject() as AsymmetricKeyParameter; ;
pr.Reader.Close();
return Base64.ToBase64String(PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp).GetEncoded());
}
} public static string ReadPublicKey(string text)
{
if (!text.StartsWith("-----BEGIN PUBLIC KEY-----"))
{
return text;
}
using (var reader = new StringReader(text))
{
var pr = new PemReader(reader);
var keyPair = pr.ReadObject() as AsymmetricCipherKeyPair;
pr.Reader.Close(); var subjectPublicKeyInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair?.Public);
returnBase64.ToBase64String(subjectPublicKeyIno.GetEncoded());
}
}

PEM格式密钥写入

public static string WritePkcs1PrivateKey(string privateKey)
{
if (privateKey.StartsWith("-----BEGIN RSA PRIVATE KEY-----"))
{
return privateKey;
} var akp = RSAUtilities.GetAsymmetricKeyParameterFormPrivateKey(privateKey);
using (var sw = new StringWriter())
{
var pWrt = new PemWriter(sw);
pWrt.WriteObject(akp);
pWrt.Writer.Close();
return sw.ToString();
}
} public static string WritePkcs8PrivateKey(string privateKey)
{
if (privateKey.StartsWith("-----BEGIN PRIVATE KEY-----"))
{
return privateKey;
} var akp = RSAUtilities.GetAsymmetricKeyParameterFormAsn1PrivateKey(privateKey); using (var sw = new StringWriter())
{
var pWrt = new PemWriter(sw);
var pkcs8 = new Pkcs8Generator(akp);
pWrt.WriteObject(pkcs8);
pWrt.Writer.Close();
return sw.ToString();
}
} public static string WritePublicKey(string publicKey)
{
if (publicKey.StartsWith("-----BEGIN PUBLIC KEY-----"))
{
return publicKey;
}
var akp = RSAUtilities.GetAsymmetricKeyParameterFormPublicKey(publicKey);
using (var sw = new StringWriter())
{
var pWrt = new PemWriter(sw);
pWrt.WriteObject(akp);
pWrt.Writer.Close();
return sw.ToString();
}
}

RSA加解密

获取非对称秘钥参数(AsymmetricKeyParameter)

/// <summary>
/// -----BEGIN RSA PRIVATE KEY-----
/// ...
/// -----END RSA PRIVATE KEY-----
/// </summary>
/// <param name="privateKey">Pkcs1格式私钥</param>
/// <returns></returns>
public static AsymmetricKeyParameter GetAsymmetricKeyParameterFormPrivateKey(string privateKey)
{
if (string.IsNullOrEmpty(privateKey))
{
throw new ArgumentNullException(nameof(privateKey));
} var instance = RsaPrivateKeyStructure.GetInstance(Base64.Decode(privateKey));
return new RsaPrivateCrtKeyParameters(instance.Modulus, instance.PublicExponent, instance.PrivateExponent,instance.Prime1, instance.Prime2, instance.Exponent1, instance.Exponent2, instance.Coefficient);
} /// <summary>
/// -----BEGIN PRIVATE KEY-----
/// ...
/// -----END PRIVATE KEY-----
/// </summary>
/// <param name="privateKey">Pkcs8格式私钥</param>
/// <returns></returns>
public static AsymmetricKeyParameter GetAsymmetricKeyParameterFormAsn1PrivateKey(string privateKey)
{
return PrivateKeyFactory.CreateKey(Base64.Decode(privateKey));
} /// <summary>
/// -----BEGIN PUBLIC KEY-----
/// ...
/// -----END PUBLIC KEY-----
/// </summary>
/// <param name="publicKey">公钥</param>
/// <returns></returns>
public static AsymmetricKeyParameter GetAsymmetricKeyParameterFormPublicKey(string publicKey)
{
if (string.IsNullOrEmpty(publicKey))
{
throw new ArgumentNullException(nameof(publicKey));
} return PublicKeyFactory.CreateKey(Base64.Decode(publicKey));
}

RSA加解与解密

 /// <summary>
/// RSA加密
/// </summary>
/// <param name="data">未加密数据字节数组</param>
/// <param name="parameters">非对称密钥参数</param>
/// <param name="algorithm">密文算法</param>
/// <returns>已加密数据字节数组</returns>
public static byte[] Encrypt(byte[] data, AsymmetricKeyParameter parameters, string algorithm)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
if (parameters == null)
{
throw new ArgumentNullException(nameof(parameters));
}
if (string.IsNullOrEmpty(algorithm))
{
throw new ArgumentNullException(nameof(algorithm));
} var bufferedCipher = CipherUtilities.GetCipher(algorithm);
bufferedCipher.Init(true, parameters);
return bufferedCipher.DoFinal(data);
} /// <summary>
/// RSA解密
/// </summary>
/// <param name="data">已加密数据字节数组</param>
/// <param name="parameters">非对称密钥参数</param>
/// <param name="algorithm">密文算法</param>
/// <returns>未加密数据字节数组</returns>
public static byte[] Decrypt(byte[] data, AsymmetricKeyParameter parameters, string algorithm)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
if (parameters == null)
{
throw new ArgumentNullException(nameof(parameters));
}
if (string.IsNullOrEmpty(algorithm))
{
throw new ArgumentNullException(nameof(algorithm));
}
var bufferedCipher = CipherUtilities.GetCipher(algorithm);
bufferedCipher.Init(false, parameters);
return bufferedCipher.DoFinal(data);
} /// <summary>
/// RSA加密——Base64
/// </summary>
/// <param name="data">未加密字符串</param>
/// <param name="parameters">非对称密钥参数</param>
/// <param name="algorithm">密文算法</param>
/// <returns>已加密Base64字符串</returns>
public static string EncryptToBase64(string data, AsymmetricKeyParameter parameters, string algorithm)
{
return Base64.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(data), parameters, algorithm));
} /// <summary>
/// RSA解密——Base64
/// </summary>
/// <param name="data">已加密Base64字符串</param>
/// <param name="parameters">非对称密钥参数</param>
/// <param name="algorithm">密文算法</param>
/// <returns>未加密字符串</returns>
public static string DecryptFromBase64(string data, AsymmetricKeyParameter parameters, string algorithm)
{
return Encoding.UTF8.GetString(Decrypt(Base64.Decode(data), parameters, algorithm));
} /// <summary>
/// RSA加密——十六进制
/// </summary>
/// <param name="data">未加密字符串</param>
/// <param name="parameters">非对称密钥参数</param>
/// <param name="algorithm">密文算法</param>
/// <returns>已加密十六进制字符串</returns>
public static string EncryptToHex(string data, AsymmetricKeyParameter parameters, string algorithm)
{
return Hex.ToHexString(Encrypt(Encoding.UTF8.GetBytes(data), parameters, algorithm));
} /// <summary>
/// RSA解密——十六进制
/// </summary>
/// <param name="data">已加密十六进制字符串</param>
/// <param name="parameters">非对称密钥参数</param>
/// <param name="algorithm">密文算法</param>
/// <returns>未加密字符串</returns>
public static string DecryptFromHex(string data, AsymmetricKeyParameter parameters, string algorithm)
{
return Encoding.UTF8.GetString(Decrypt(Hex.Decode(data), parameters, algorithm));
}

RSA密文算法

public const string RSA_NONE_NoPadding = "RSA/NONE/NoPadding";
public const string RSA_NONE_PKCS1Padding = "RSA/NONE/PKCS1Padding";
public const string RSA_NONE_OAEPPadding = "RSA/NONE/OAEPPadding";
public const string RSA_NONE_OAEPWithSHA1AndMGF1Padding = "RSA/NONE/OAEPWithSHA1AndMGF1Padding";
public const string RSA_NONE_OAEPWithSHA224AndMGF1Padding = "RSA/NONE/OAEPWithSHA224AndMGF1Padding";
public const string RSA_NONE_OAEPWithSHA256AndMGF1Padding = "RSA/NONE/OAEPWithSHA256AndMGF1Padding";
public const string RSA_NONE_OAEPWithSHA384AndMGF1Padding = "RSA/NONE/OAEPWithSHA384AndMGF1Padding";
public const string RSA_NONE_OAEPWithMD5AndMGF1Padding = "RSA/NONE/OAEPWithMD5AndMGF1Padding"; public const string RSA_ECB_NoPadding = "RSA/ECB/NoPadding";
public const string RSA_ECB_PKCS1Padding = "RSA/ECB/PKCS1Padding";
public const string RSA_ECB_OAEPPadding = "RSA/ECB/OAEPPadding";
public const string RSA_ECB_OAEPWithSHA1AndMGF1Padding = "RSA/ECB/OAEPWithSHA1AndMGF1Padding";
public const string RSA_ECB_OAEPWithSHA224AndMGF1Padding = "RSA/ECB/OAEPWithSHA224AndMGF1Padding";
public const string RSA_ECB_OAEPWithSHA256AndMGF1Padding = "RSA/ECB/OAEPWithSHA256AndMGF1Padding";
public const string RSA_ECB_OAEPWithSHA384AndMGF1Padding = "RSA/ECB/OAEPWithSHA384AndMGF1Padding";
public const string RSA_ECB_OAEPWithMD5AndMGF1Padding = "RSA/ECB/OAEPWithMD5AndMGF1Padding"; ......

编码算法

大家要明白,不管是对称算法还是非对称算法,其输入与输出均是字节数组,通常我们要结合编码算法对加密之后或解密之前的数据,进行编码操作。

BouncyCastle提供的Base64编码算法

namespace Org.BouncyCastle.Utilities.Encoders
{
public sealed class Base64
{
//
public static byte[] Decode(byte[] data);
//
public static byte[] Decode(string data);
//
public static int Decode(string data, Stream outStream);
//
public static byte[] Encode(byte[] data);
//
public static byte[] Encode(byte[] data, int off, int length);
//
public static int Encode(byte[] data, Stream outStream);
//
public static int Encode(byte[] data, int off, int length, Stream outStream);
public static string ToBase64String(byte[] data);
public static string ToBase64String(byte[] data, int off, int length);
}
}

BouncyCastle提供的Hex十六进制编码算法

namespace Org.BouncyCastle.Utilities.Encoders
{
//
// 摘要:
// Class to decode and encode Hex.
public sealed class Hex
{
//
public static byte[] Decode(byte[] data);
//
public static byte[] Decode(string data);
//
public static int Decode(string data, Stream outStream);
//
public static byte[] Encode(byte[] data);
//
public static byte[] Encode(byte[] data, int off, int length);
//
public static int Encode(byte[] data, Stream outStream);
//
public static int Encode(byte[] data, int off, int length, Stream outStream);
public static string ToHexString(byte[] data);
public static string ToHexString(byte[] data, int off, int length);
}
}

RSA加解密示例

private static void RSA_ECB_PKCS1Padding()
{
var data = "hello rsa"; Console.WriteLine($"加密原文:{data}"); // rsa pkcs8 private key encrypt
//algorithm rsa/ecb/pkcs1padding
var pkcs8data = RSA.EncryptToBase64(data, RSAUtilities.GetAsymmetricKeyParameterFormAsn1PrivateKey(pkcs8_1024_private_key),CipherAlgorithms.RSA_ECB_PKCS1Padding); Console.WriteLine("密钥格式:pkcs8,密文算法:rsa/ecb/pkcs1padding,加密结果");
Console.WriteLine(pkcs8data); //rsa pkcs1 private key encrypt
//algorithm rsa/ecb/pkcs1padding
var pkcs1data = RSA.EncryptToBase64(data, RSAUtilities.GetAsymmetricKeyParameterFormPrivateKey(pkcs1_1024_private_key),CipherAlgorithms.RSA_ECB_PKCS1Padding); Console.WriteLine($"密钥格式:pkcs1,密文算法:rsa/ecb/pkcs1padding");
Console.WriteLine(pkcs1data); Console.WriteLine($"加密结果比对是否一致:{pkcs8data.Equals(pkcs1data)}"); var _1024_public_key = RSAKeyConverter.GetPublicKeyFromPrivateKeyPkcs1(pkcs1_1024_private_key); Console.WriteLine($"从pkcs1私钥中提取公钥:");
Console.WriteLine(_1024_public_key); Console.WriteLine("使用公钥解密数据:");
//rsa public key decrypt
//algorithm rsa/ecb/pkcs1padding
Console.WriteLine(RSA.DecryptFromBase64(pkcs1data, RSAUtilities.GetAsymmetricKeyParameterFormPublicKey(_1024_public_key),CipherAlgorithms.RSA_ECB_PKCS1Padding)); Console.WriteLine();
}

下期预告

下一篇将介绍哈希算法(HMACSHA1、HMACSHA256、SHA1、SHA1WithRSA、SHA256、SHA256WithRSA),敬请期待...

.NET Core加解密实战系列之——RSA非对称加密算法的更多相关文章

  1. .NET Core加解密实战系列之——消息摘要与数字签名算法

    目录 简介 功能依赖 消息摘要算法 MD算法 家族发展史 应用场景 代码实现 MD5 示例代码 SHA算法 应用场景 代码实现 SHA1 SHA256 示例代码 MAC算法 HMAC算法的典型应用 H ...

  2. .NET Core加解密实战系列之——使用BouncyCastle制作p12(.pfx)数字证书

    简介 加解密现状,编写此系列文章的背景: 需要考虑系统环境兼容性问题(Linux.Windows) 语言互通问题(如C#.Java等)(加解密本质上没有语言之分,所以原则上不存在互通性问题) 网上资料 ...

  3. .NET Core加解密实战系列之——对称加密算法

    简介 加解密现状,编写此系列文章的背景: 需要考虑系统环境兼容性问题(Linux.Windows) 语言互通问题(如C#.Java等)(加解密本质上没有语言之分,所以原则上不存在互通性问题) 网上资料 ...

  4. 9.Java 加解密技术系列之 RSA

    Java 加解密技术系列之 RSA 序 概念 工作流程 RSA 代码实现 加解密结果 结束语 序 距 离上一次写博客感觉已经很长时间了,先吐槽一下,这个月以来,公司一直在加班,又是发版.上线,又是新项 ...

  5. Java 加解密技术系列文章

    Java 加解密技术系列之 总结 Java 加解密技术系列之 DH Java 加解密技术系列之 RSA Java 加解密技术系列之 PBE Java 加解密技术系列之 AES Java 加解密技术系列 ...

  6. 10.Java 加解密技术系列之 DH

    Java 加解密技术系列之 DH 序 概念 原理 代码实现 结果 结束语 序 上一篇文章中简单的介绍了一种非对称加密算法 — — RSA,今天这篇文章,继续介绍另一种非对称加密算法 — — DH.当然 ...

  7. 11.Java 加解密技术系列之 总结

    Java 加解密技术系列之 总结 序 背景 分类 常用算法 原理 关于代码 结束语 序 上一篇文章中简单的介绍了第二种非对称加密算法 — — DH,这种算法也经常被叫做密钥交换协议,它主要是针对密钥的 ...

  8. 8.Java 加解密技术系列之 PBE

    Java 加解密技术系列之 PBE 序 概念 原理 代码实现 结束语 序 前 边的几篇文章,已经讲了几个对称加密的算法了,今天这篇文章再介绍最后一种对称加密算法 — — PBE,这种加密算法,对我的认 ...

  9. 7.java 加解密技术系列之 AES

    java 加解密技术系列之 AES 序 概念 原理 应用 代码实现 结束语 序 这篇文章继续介绍对称加密算法,至于今天的主角,不用说,也是个厉害的角色 — — AES.AES 的出现,就是为了来替代原 ...

随机推荐

  1. jsp循环map map的key值不固定

    <c:if test="${not empty parammap}"> <c:forEach items="${parammap }" var ...

  2. Spring Boot 教程(2) - Mybatis

    Spring Boot 教程 - Mybatis 1. 什么是Mybatis? MyBatis 是一款优秀的持久层框架,它支持自定义 SQL.存储过程以及高级映射.MyBatis 免除了几乎所有的 J ...

  3. rfind()的使用

    今天学了一个新函数 rfind 使用: str=123/456 str.rfind('/',1,6) 返回的是从1到6找最后一个/的位置

  4. 二,表格<table>的使用细节

    如有不足请不吝赐教!最先接触的布局表格,表格灵活性,加载速度都不如<div>灵活,但是对于萌新来说再定位某些,例如div里面套文字,而刚接触html+css又不懂得那么多使用<spa ...

  5. pyqt5-多线程初步

    多线程是实现并发的一个重要手段.在GUI编程中,经常需要将耗费时间较多的任务分离出来成为一个线程,避免对主线程造成影响(造成界面无响应). 在Qt中,最简单的多线程主要通过继承QThread类实现,重 ...

  6. [PHP学习教程 - 网络]002.$_SERVER["SCRIPT_NAME"]、$_SERVER["PHP_SELF"]、$_SERVER["QUERY_STRING"]、$_SERVER["REQUEST_URI"]介绍($_SERVER URL Infomation)

    引言:在使用原生PHP的时候,对于URL路径的切割,如:域名,查询参数等等的提取,通常绝大多数兄弟会忽略$_SERVER中定义的内置常量的关系,这里为大家讲解一下. 常用的URL请求路径$_SERVE ...

  7. [安卓基础] 005.创建一个简单的UI

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  8. Function's dict

    众所周知,Python是没有switch的,那么只能使用 if else来进行判断,但是if else比较冗长, 使用太多的if else 代码看起来不简洁,如下 student.py def stu ...

  9. Linux目录遍历opendir()

    头文件:#include<dirent.h> DIR *opendir(const char *dirname); 打开目录 struct dirent *readdir(DIR *dir ...

  10. Alpha冲刺 —— 5.5

    这个作业属于哪个课程 软件工程 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 Alpha冲刺 作业正文 正文 github链接 项目地址 其他参考文献 无 一.会议内容 1.展 ...