对文本或文件进行数字签名。
Kotlin 代码:
代码区域可编辑,点击右上角可运行,运行结果在代码底部。
公钥、私钥和签名内容均以 Base64 编码为字符串。
SignatureToolbox
中的方法:
createKeyPair()
signText()
/signFile()
verifyTextSign()
/verifyFileSign()
密钥算法是 DSA
,长度 2048
,签名算法是 SHA256withDSA
。编辑代码中的这些常量可以变更算法。
@tasy5kg,以下是将给定的Kotlin代码转换为Java代码后的结果:
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class Main {
private static final String KEY_PAIR_GENERATOR_ALGORITHM = "DSA";
private static final int KEY_SIZE = 2048;
private static final String SIGNATURE_ALGORITHM = "SHA256withDSA";
private static final int FILE_BUFFER_SIZE = 4096;
public static void main(String[] args) {
SignatureToolbox signatureToolbox = SignatureToolbox.getInstance();
SignatureToolbox.KeyPairBase64 keyPair = signatureToolbox.createKeyPair();
String publicKey = keyPair.getPublicKey();
String privateKey = keyPair.getPrivateKey();
System.out.println("New key pair created.");
System.out.println("Public key: " + publicKey);
System.out.println("Private key: " + privateKey);
String textToSign = "这里是要被数字签名的文字。";
System.out.println("Text to sign: " + textToSign);
String signature = signatureToolbox.signText(textToSign, privateKey);
System.out.println("Signature: " + signature);
System.out.println("Verify signature: " + signatureToolbox.verifyTextSign(textToSign, publicKey, signature));
}
static class SignatureToolbox {
private static final String KEY_PAIR_GENERATOR_ALGORITHM = Main.KEY_PAIR_GENERATOR_ALGORITHM;
private static final int KEY_SIZE = Main.KEY_SIZE;
private static final String SIGNATURE_ALGORITHM = Main.SIGNATURE_ALGORITHM;
private static final int FILE_BUFFER_SIZE = Main.FILE_BUFFER_SIZE;
private static SignatureToolbox instance;
private SignatureToolbox() {
}
public static SignatureToolbox getInstance() {
if (instance == null) {
instance = new SignatureToolbox();
}
return instance;
}
public KeyPairBase64 createKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_PAIR_GENERATOR_ALGORITHM);
keyPairGenerator.initialize(KEY_SIZE);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return new KeyPairBase64(keyPair);
}
public String signText(String text, String privateKeyBase64) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(base64ToPrivateKey(privateKeyBase64));
signature.update(text.getBytes());
byte[] signedBytes = signature.sign();
return toBase64(signedBytes);
}
public String signFile(String filePath, String privateKeyBase64) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(base64ToPrivateKey(privateKeyBase64));
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(filePath));
byte[] buffer = new byte[FILE_BUFFER_SIZE];
int len;
while ((len = bufferedInputStream.read(buffer)) >= 0) {
signature.update(buffer, 0, len);
}
bufferedInputStream.close();
byte[] signedBytes = signature.sign();
return toBase64(signedBytes);
}
public boolean verifyTextSign(String text, String publicKeyBase64, String signatureBase64) throws Exception {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(base64ToPublicKey(publicKeyBase64));
signature.update(text.getBytes());
byte[] signatureBytes = base64ToByteArray(signatureBase64);
return signature.verify(signatureBytes);
}
public boolean verifyFileSign(String filePath, String publicKeyBase64,
import java.io.BufferedInputStream
import java.io.FileInputStream
import java.security.KeyFactory
import java.security.KeyPair
import java.security.KeyPairGenerator
import java.security.Signature
import java.security.spec.PKCS8EncodedKeySpec
import java.security.spec.X509EncodedKeySpec
import java.util.Base64
fun main() {
with(SignatureToolbox) {
val keyPair = createKeyPair()
val publicKey = keyPair.publicKey
val privateKey = keyPair.privateKey
println("New key pair created.")
println("Public key: $publicKey")
println("Private key: $privateKey")
val textToSign = "这里是要被数字签名的文字。"
println("Text to sign: $textToSign")
val signature = signText(textToSign, privateKey)
println("Signature: $signature")
println("Verify signature: ${verifyTextSign(textToSign, publicKey, signature)}")
}
}
object SignatureToolbox {
private const val KEY_PAIR_GENERATOR_ALGORITHM = "DSA"
private const val KEY_SIZE = 2048
private const val SIGNATURE_ALGORITHM = "SHA256withDSA"
private const val FILE_BUFFER_SIZE = 4096
data class KeyPairBase64(val publicKey: String, val privateKey: String) {
constructor(keyPair: KeyPair) : this(keyPair.public.encoded.toBase64(), keyPair.private.encoded.toBase64())
}
fun createKeyPair() =
with(KeyPairGenerator.getInstance(KEY_PAIR_GENERATOR_ALGORITHM)) {
initialize(KEY_SIZE)
KeyPairBase64(generateKeyPair())
}
fun signText(text: String, privateKeyBase64: String) =
with(Signature.getInstance(SIGNATURE_ALGORITHM)) {
initSign(privateKeyBase64.base64ToPrivateKey())
update(text.toByteArray())
sign().toBase64()
}
fun signFile(filePath: String, privateKeyBase64: String) =
with(Signature.getInstance(SIGNATURE_ALGORITHM)) {
initSign(privateKeyBase64.base64ToPrivateKey())
val bufferedInputStream = BufferedInputStream(FileInputStream(filePath))
val buffer = ByteArray(FILE_BUFFER_SIZE)
var len: Int
while (bufferedInputStream.read(buffer).also { len = it } >= 0) {
update(buffer, 0, len)
}
bufferedInputStream.close()
sign().toBase64()
}
fun verifyTextSign(text: String, publicKeyBase64: String, signatureBase64: String) =
with(Signature.getInstance(SIGNATURE_ALGORITHM)) {
initVerify(publicKeyBase64.base64ToPublicKey())
update(text.toByteArray())
verify(signatureBase64.base64ToByteArray())
}
fun verifyFileSign(filePath: String, publicKeyBase64: String, signatureBase64: String) =
with(Signature.getInstance(SIGNATURE_ALGORITHM)) {
initVerify(publicKeyBase64.base64ToPublicKey())
val bufferedInputStream = BufferedInputStream(FileInputStream(filePath))
val buffer = ByteArray(FILE_BUFFER_SIZE)
var len: Int
while (bufferedInputStream.available() != 0) {
len = bufferedInputStream.read(buffer)
update(buffer, 0, len)
}
bufferedInputStream.close()
verify(signatureBase64.base64ToByteArray())
}
private fun String.base64ToPublicKey() =
KeyFactory.getInstance(KEY_PAIR_GENERATOR_ALGORITHM)
.generatePublic(X509EncodedKeySpec(this.base64ToByteArray()))
private fun String.base64ToPrivateKey() =
KeyFactory.getInstance(KEY_PAIR_GENERATOR_ALGORITHM)
.generatePrivate(PKCS8EncodedKeySpec(this.base64ToByteArray()))
private fun String.base64ToByteArray() = Base64.getDecoder().decode(this)!!
private fun ByteArray.toBase64() = Base64.getEncoder().encodeToString(this)!!
}