本章记录关于Java MD5withRSA加密算法的C#实现。由于C#不提供MD5withRSA的内置实现,所以必须依赖其他的第三方库。这里提供一个简单的sample来演绎[bouncycastle]的加密库。

MD5withRSA是什么?

  1. 先使用MD5加密(不可逆转) 生成密文。
  2. 使用RSA继续加密 上一步的密文。

MD5是什么?

Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。该算法的文件号为RFC 1321(R.Rivest,MIT Laboratory for Computer Science and RSA Data Security Inc. April 1992)。 –来自百度百科

RSA是什么?

RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。 –来自百度百科

MD5withRSA 的使用场景

如果你在百度上搜索 MD5withRSA 恐怕搜到最多的就是关于建行支付的。对的,这个加密算法常用与支付阶段。主要用途是防篡改。一般来说传递明文 可能被黑客从传输阶段拦截,篡改,此时我们用私钥将MD5加密后的密文再加密与明文一起发送。服务器用公匙将密文解密此时得到md5的密文,然后将明文用md5加密得到密文,匹配这两个密文。如果一致则消息是未被篡改的。

使用 BouncyCastle.Crypto.dll 演绎签名与验证签名

加密支持列表

Current feature list:

Generation and parsing of PKCS-12 files.
X.509: Generators and parsers for V1 and V3 certificates, V2 CRLs and attribute certificates.
PBE algorithms supported by PbeUtilities: PBEwithMD2andDES-CBC, PBEwithMD2andRC2-CBC, PBEwithMD5andDES-CBC, PBEwithMD5andRC2-CBC, PBEwithSHA1andDES-CBC, PBEwithSHA1andRC2-CBC, PBEwithSHA-1and128bitRC4, PBEwithSHA-1and40bitRC4, PBEwithSHA-1and3-keyDESEDE-CBC, PBEwithSHA-1and2-keyDESEDE-CBC, PBEwithSHA-1and128bitRC2-CBC, PBEwithSHA-1and40bitRC2-CBC, PBEwithHmacSHA-1, PBEwithHmacSHA-224, PBEwithHmacSHA-256, PBEwithHmacRIPEMD128, PBEwithHmacRIPEMD160, and PBEwithHmacRIPEMD256.
Signature algorithms supported by SignerUtilities: MD2withRSA, MD4withRSA, MD5withRSA, RIPEMD128withRSA, RIPEMD160withECDSA, RIPEMD160withRSA, RIPEMD256withRSA, SHA-1withRSA, SHA-224withRSA, SHA-256withRSAandMGF1, SHA-384withRSAandMGF1, SHA-512withRSAandMGF1, SHA-1withDSA, and SHA-1withECDSA.
Symmetric key algorithms: AES, Blowfish, Camellia, CAST5, CAST6, ChaCha, DES, DESede, GOST28147, HC-128, HC-256, IDEA, ISAAC, Noekeon, RC2, RC4, RC5-32, RC5-64, RC6, Rijndael, Salsa20, SEED, Serpent, Skipjack, TEA/XTEA, Threefish, Tnepres, Twofish, VMPC and XSalsa20.
Symmetric key modes: CBC, CFB, CTS, GOFB, OFB, OpenPGPCFB, and SIC (or CTR).
Symmetric key paddings: ISO10126d2, ISO7816d4, PKCS-5/7, TBC, X.923, and Zero Byte.
Asymmetric key algorithms: ElGamal, DSA, ECDSA, NaccacheStern and RSA (with blinding).
Asymmetric key paddings/encodings: ISO9796d1, OAEP, and PKCS-1.
AEAD block cipher modes: CCM, EAX, GCM and OCB.
Digests: GOST3411, Keccak, MD2, MD4, MD5, RIPEMD128, RIPEMD160, RIPEMD256, RIPEMD320, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA3, Tiger, and Whirlpool.
XOFs: SHAKE.
Signer mechanisms: DSA, ECDSA, ECGOST3410, ECNR, GOST3410, ISO9796d2, PSS, RSA, X9.31-1998.
Key Agreement: Diffie-Hellman, EC-DH, EC-MQV, J-PAKE, SRP-6a.
Macs: CBCBlockCipher, CFBBlockCipher, CMAC, GMAC, GOST28147, HMac, ISO9797 Alg. 3, Poly1305, SipHash, SkeinMac, VMPCMAC.
PBE generators: PKCS-12, and PKCS-5 - schemes 1 and 2.
OpenPGP (RFC 4880)
Cryptographic Message Syntax (CMS, RFC 3852), including streaming API.
Online Certificate Status Protocol (OCSP, RFC 2560).
Time Stamp Protocol (TSP, RFC 3161).
TLS/DTLS client/server up to version 1.2, with support for the most common ciphersuites and extensions, and many less common ones. Non-blocking API available.
Elliptic Curve Cryptography: support for generic F2m and Fp curves, high-performance custom implementations for many standardized curves.
Reading/writing of PEM files, including RSA and DSA keys, with a variety of encryptions.
PKIX certificate path validation

Sample

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/// <summary>
/// MD5withRSA Signing
/// https://www.vrast.cn
/// keyle_xiao 2017.1.12
/// </summary>
public class MD5withRSASigning
{
public Encoding encoding = Encoding.UTF8;
public string SignerSymbol = "MD5withRSA";

public MD5withRSASigning() { }

public MD5withRSASigning(Encoding e, string s)
{
encoding = e;
SignerSymbol = s;
}

private AsymmetricKeyParameter CreateKEY(bool isPrivate, string key)
{
byte[] keyInfoByte = Convert.FromBase64String(key);

if (isPrivate)
return PrivateKeyFactory.CreateKey(keyInfoByte);
else
return PublicKeyFactory.CreateKey(keyInfoByte);
}

public string Sign(string content, string privatekey)
{
ISigner sig = SignerUtilities.GetSigner(SignerSymbol);

sig.Init(true, CreateKEY(true, privatekey));

var bytes = encoding.GetBytes(content);

sig.BlockUpdate(bytes, 0, bytes.Length);
byte[] signature = sig.GenerateSignature();


/* Base 64 encode the sig so its 8-bit clean */
var signedString = Convert.ToBase64String(signature);

return signedString;
}

public bool Verify(string content, string signData, string publickey)
{
ISigner signer = SignerUtilities.GetSigner(SignerSymbol);

signer.Init(false, CreateKEY(false, publickey));

var expectedSig = Convert.FromBase64String(signData);

/* Get the bytes to be signed from the string */
var msgBytes = encoding.GetBytes(content);

/* Calculate the signature and see if it matches */
signer.BlockUpdate(msgBytes, 0, msgBytes.Length);
return signer.VerifySignature(expectedSig);
}
}


参考文档

bouncycastle官网
C# 与JAVA 的RSA 加密解密交互,互通,C#使用BouncyCastle来实现私钥加密,公钥解密的方法