数字签名算法之RSA
1.数字签名简述2. 模型分析3. 代码实现3.1 签名算法实现3.2 测试代码3.3 运行结果
1.数字签名简述
数字签名算法可以看做是一种带有密钥的消息摘要算法,并且这种密钥包含了公钥和私钥。也就是说数字签名算法是非对称加密算法和消息摘要算法的结合体。
数字签名算法是公钥基础设施(PKI)以及许多网络安全机制(SSL/TLS、VPN等)的基础。
数字签名算法能够验证数据的完整性、认证性以及抗否认性。
数字签名算法遵循“私钥签名,公钥验证” 的签名/验证方式。
数字签名算法主要包括 RSA、DSA和ECDSA共3种算法。其中,RSA算法源于整数因子分解问题,DSA和ECDSA算法源于离散对数问题。
RSA既是加密/解密算法, 也是签名算法。
DSA只有签名算法,其基于DSS算法。
ECDSA算法是ECC算法与DSA算法的结合,想对于传统签名算法,具有速度快、强度高、签名短等优点,被广泛应用。
2. 模型分析
Alice作为发送方,Bob作为接收方,交互流程如下所示。
3. 代码实现
Java与Bouncy Castle对RSA签名算法均有实现,具体细节如下表所示。
算法密钥长度密钥长度默认值签名长度备注
MD2withRSA、MD5withRSA、SHA1withRSA512~65536位(密钥长度必须是64的倍数)1024与密钥长度相同JavaSHA224withRSA、SHA256withRSA、SHA384withRSA、SHA512withRSA 、RIPEMD128withRSA、RIPEMD160withRSA512~65536位(密钥长度必须是64的倍数)2048与密钥长度相同Bouncy Castle实现
3.1 签名算法实现
下面是Java对RSA数字签名的实现
public static final String KEY_ALGORITHM
= "RSA";
public static final String SIGNATURE_ALGORITHM
= "MD5withRSA";
private static final String PUBLIC_KEY
= "RSAPublicKey";
private static final String PRIVATE_KEY
= "RSAPrivateKey";
private static final int KEY_SIZE
= 512;
public static byte[] sign(byte[] data
, byte[] privateKey
) throws Exception
{
PKCS8EncodedKeySpec pkcs8KeySpec
= new PKCS8EncodedKeySpec(privateKey
);
KeyFactory keyFactory
= KeyFactory
.getInstance(KEY_ALGORITHM
);
PrivateKey priKey
= keyFactory
.generatePrivate(pkcs8KeySpec
);
Signature signature
= Signature
.getInstance(SIGNATURE_ALGORITHM
);
signature
.initSign(priKey
);
signature
.update(data
);
return signature
.sign();
}
public static boolean verity(byte[] data
, byte[] publicKey
, byte[] sign
) throws Exception
{
X509EncodedKeySpec keySpec
= new X509EncodedKeySpec(publicKey
);
KeyFactory keyFactory
= KeyFactory
.getInstance(KEY_ALGORITHM
);
PublicKey pubKey
= keyFactory
.generatePublic(keySpec
);
Signature signature
= Signature
.getInstance(SIGNATURE_ALGORITHM
);
signature
.initVerify(pubKey
);
signature
.update(data
);
return signature
.verify(sign
);
}
3.2 测试代码
@Test
public void rsaSignTest() throws Exception
{
Map
<String, Object> keyMap
= RSACoder
.initKey();
byte[] publicKey
= RSACoder
.getPublicKey(keyMap
);
byte[] privateKey
= RSACoder
.getPrivateKey(keyMap
);
System
.out
.println("公钥:\n"+Base64
.encodeToString(publicKey
, Base64
.DEFAULT
));
System
.out
.println("私钥:\n"+Base64
.encodeToString(privateKey
, Base64
.DEFAULT
));
String inputStr
= "RSA数字签名";
byte[] data
= inputStr
.getBytes();
byte[] sign
= RSACoder
.sign(data
, privateKey
);
System
.out
.println("签名:\t"+ Hex
.toHexString(sign
));
boolean status
= RSACoder
.verity(data
, publicKey
, sign
);
System
.out
.println("验签状态:\t"+ status
);
assertTrue(status
);
}
3.3 运行结果
2020-10-21 14:28:20.130 15667-15682/com.calvin.android.demo2 I/System.out: 公钥:
2020-10-21 14:28:20.130 15667-15682/com.calvin.android.demo2 I/System.out: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALVI158wtZj4N7Fhndfr0SxspYaoVJAYTcgR1czsgnTy
2020-10-21 14:28:20.130 15667-15682/com.calvin.android.demo2 I/System.out: Qz0cjuyVWqXFlxK3ZitLvuzuQqEKAHZkBSggBPxA660CAwEAAQ
==
2020-10-21 14:28:20.130 15667-15682/com.calvin.android.demo2 I/System.out: 私钥:
2020-10-21 14:28:20.130 15667-15682/com.calvin.android.demo2 I/System.out: MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAtUjXnzC1mPg3sWGd1+vRLGylhqhU
2020-10-21 14:28:20.130 15667-15682/com.calvin.android.demo2 I/System.out: kBhNyBHVzOyCdPJDPRyO7JVapcWXErdmK0u+7O5CoQoAdmQFKCAE/EDrrQIDAQABAkEApjyaxXbE
2020-10-21 14:28:20.130 15667-15682/com.calvin.android.demo2 I/System.out: P/b2EynhtXugf61NiJLZoJ04zktUlCsZYiSu2V575e1uRahiv9Z9tO6otYbBQDb8DwtdjlgH0usw
2020-10-21 14:28:20.131 15667-15682/com.calvin.android.demo2 I/System.out: 4QIhANlMi777d9j+QVB1tw16FblEXm1YFBAW4WxAoAtFkM4ZAiEA1ZJD+A3wlhNLe5L9Zo9t7dHm
2020-10-21 14:28:20.131 15667-15682/com.calvin.android.demo2 I/System.out: qlrlyxDY5MOBq40XVLUCIFylfDeTM8f6r5JEfiVq1fRFqBTqprMtbjMfYp0rrc+RAiBPDGkt6fLv
2020-10-21 14:28:20.131 15667-15682/com.calvin.android.demo2 I/System.out: iUq5/WjfSh01FijbSvOc2qp82cQn+/vztQIhAIe/Rez3m7xmEzvL45IOVxfw7x0dwexDXdGdIIjo
2020-10-21 14:28:20.131 15667-15682/com.calvin.android.demo2 I/System.out: o9ak
2020-10-21 14:28:20.135 15667-15682/com.calvin.android.demo2 I/System.out: 签名: 612945943b56154cc6dce2bb13597ca734f6be79ea6e86191d34378271143a65405feeb9cbec9a1327166efa285ca117123a5bb26f0eb900e161b3ceb7b35224
2020-10-21 14:28:20.136 15667-15682/com.calvin.android.demo2 I/System.out: 验签状态:
true