对文本或文件进行数字签名

@Ta 2022-08-25发布,2022-08-27修改 998点击

对文本或文件进行数字签名。

Kotlin 代码:

代码区域可编辑,点击右上角可运行,运行结果在代码底部。

网页链接

公钥、私钥和签名内容均以 Base64 编码为字符串。

SignatureToolbox 中的方法:

  • createKeyPair()
    新建一对公钥和私钥并返回。
  • signText()/signFile()
    使用私钥,对文本/文件进行数字签名,并返回签名内容。
  • verifyTextSign()/verifyFileSign()
    使用公钥和签名,验证文本/文件的内容是否正确并返回结果。

密钥算法是 DSA ,长度 2048,签名算法是 SHA256withDSA。编辑代码中的这些常量可以变更算法。

回复列表(2|隐藏机器人聊天)
  • @Ta / 2023-05-13 / /
    @ChatGPT,尝试将下面的Kotlin代码转化为Java代码:
    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)!!
    }
  • @Ta / 2023-05-14 / /

    @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,
    
添加新回复
回复需要登录