必备基础:加签验签

news/2024/11/29 8:01:41/

必备基础:加签验签

  • 1 密码学相关概念
    • 1.1 明文、密文、密钥、加密、解密
    • 1.2 对称加密、非对称加密
    • 1.3 什么是公钥私钥?
  • 2 加签验签概念
  • 3 为什么需要加签验签
  • 4 常见加密相关算法简介
    • 4.1 消息摘要算法
      • 4.1.1 MD家族算法
      • 4.1.2 ShA家族算法
      • 4.1.3 MAC算法家族
    • 4.2 对称加密算法
      • 4.2.1 DES
      • 4.2.2 3DES
      • 4.2.3 AES
    • 4.3 非对称加密算法
      • 4.3.1 RSA算法
      • 4.3.2 DSA
      • 4.3.3 ECC 算法
    • 4.4 国密算法
      • 4.4.1 SM1
      • 4.4.2 SM2
      • 4.4.3 SM3
      • 4.4.4 SM4
  • 5 加签验签相关Java的API
    • 5.1 加签相关API
    • 5.2 验签相关API
  • 6 加签验签代码实现

https://mp.weixin.qq.com/s/mt4RGyhXSo7qb-86Jw8LYg

1 密码学相关概念

1.1 明文、密文、密钥、加密、解密

明文:指没有经过加密的信息/数据。
密文:明文被加密算法加密之后,会变成密文,以确保数据安全。
密钥:是一种参数,它是在明文转换为密文或将密文转换为明文的算法中输入的参数。密钥分为对称密钥与非对称密钥。
加密:将明文变成密文的过程。
解密:将密文还原为明文的过程。

1.2 对称加密、非对称加密

对称加密:加密和解密使用相同密钥的加密算法
在这里插入图片描述
非对称加密:非对称加密算法需要两个密钥(公开密钥和私有密钥)。公钥与私钥是成对存在的,如果用公钥对数据进行加密,只有对应的私钥才能解密。
在这里插入图片描述

1.3 什么是公钥私钥?

公钥与私钥是成对存在的密钥,如果用公钥对数据进行加密,只有用对应的私钥才能解密。
其实,公钥就是公开的秘钥,私钥就是要你私自保存好的秘钥。
非对称加密算法需要有一对公私钥~

假设你有一个文件,你用字母a加密,只有字母b才能解密;或者你用b加密,只有a才能解密,那么a和b就是一对公私钥。如果密钥a公开,密钥b你就要私自保存好啦,这时候密钥a就是公钥,密钥b就是私钥。相反,如果b公开,a就要保存好,这时候呢,秘钥b就是公钥,秘钥a就是私钥

2 加签验签概念

「加签」:用Hash函数把原始报文生成报文摘要,然后用私钥对这个摘要进行加密,就得到这个报文对应的数字签名。通常来说呢,请求方会把「数字签名和报文原文」一并发送给接收方。
在这里插入图片描述
「验签」:接收方拿到原始报文和数字签名后,用「同一个Hash函数」从报文中生成摘要A。另外,用对方提供的公钥对数字签名进行解密,得到摘要B,对比A和B是否相同,就可以得知报文有没有被篡改过。
在这里插入图片描述

3 为什么需要加签验签

上小节中,加签和验签我们已经知道概念啦,那么,为什么需要加签和验签呢?有些朋友可能觉得,我们不是用「公钥加密,私钥解密」就好了嘛?
接下来呢,举个demo吧。

假设现在有A公司,要接入C公司的转账系统。在一开始呢,C公司把自己的公钥寄给A公司,自己收藏好私钥。A公司这边的商户,发起转账时,A公司先用C公司的公钥,对请求报文加密,加密报文到达C公司的转账系统时,C公司就用自己的私钥把报文揭开。假设在加密的报文在传输过程中,被中间人Actor获取了,他也郁闷,因为他没有私钥,看着天鹅肉,又吃不了。本来想修改报文,给自己账号转一个亿的,哈哈。这个实现方式看起来是天衣无缝,稳得一匹的。

在这里插入图片描述

但是呢,如果一开始,C公司把公钥发给公司A的时候,就被中间人Actor获取到呢,酱紫就出问题了。

中间人Actor截取了C的公钥,他把自己的公钥发给了A公司,A误以为这就是C公司的公钥。A在发起转账时,用Actor的公钥,对请求报文加密,加密报文到在传输过程,Actor又截取了,这时候,他用自己的私钥解密,然后修改了报文(给自己转一个亿),再用C的公钥加密,发给C公司,C公司收到报文后,继续用自己的私钥解密。最后是不是A公司的转账账户损失了一个亿呢~
在这里插入图片描述

C公司是怎么区分报文是不是来自A呢,还是被中间人修改过呢?为了表明身份和报文真实性,这就需要「加签验签」啦!

A公司把自己的公钥也发送给C公司,私钥自己保留着。在发起转账时,先用自己的私钥对请求报文加签,于是得到自己的数字签名。再把数字签名和请求报文一起发送给C公司。C公司收到报文后,拿A的公钥进行验签,如果原始报文和数字签名的摘要内容不一致,那就是报文被篡改啦~

在这里插入图片描述
有些朋友可能有疑问,假设A在发自己的公钥给C公司的时候,也被中间人Actor截取了呢。嗯嗯,我们来模拟一波Actor又截取了公钥,看看Actor能干出什么事情来~哈哈

假设Actor截取到A的公钥后,随后也截取了到A发往C的报文。他截取到报文后,第一件想做的事肯定是修改报文内容。但是如果单单修改原始报文是不可以的,因为发过去C公司肯定验签不过啦。但是呢,数字签名似乎解不开,因为消息摘要算法(hash算法)无法逆向解开的,只起验证的作用呢…

所以呢,公钥与私钥是用来加密与加密的,「加签与验签是用来证明身份」,以免被篡改的。

4 常见加密相关算法简介

4.1 消息摘要算法

  • 相同的明文数据经过相同的消息摘要算法会得到相同的密文结果值。
  • 数据经过消息摘要算法处理,得到的摘要结果值,是无法还原为处理前的数据的。
  • 数据摘要算法也被称为哈希(Hash)算法或散列算法。
  • 消息摘要算法一般用于签名验签。

消息摘要算法主要分三类:MD(Message Digest,消息摘要算法)、SHA(Secure Hash Algorithm,安全散列算法)和MAC(Message Authentication Code,消息认证码算法)。

在这里插入图片描述

4.1.1 MD家族算法

MD(Message Digest,消息摘要算法)家族,包括MD2,MD4,MD5。

  • MD2,MD4,MD5 计算的结果都是是一个128位(即16字节)的散列值,用于确保信息传输完整一致。
  • MD2的算法较慢但相对安全,MD4速度很快,但安全性下降,MD5则比MD4更安全、速度更快
  • MD5被广泛应用于数据完整性校验、数据(消息)摘要、数据加密等。
  • MD5,可以被破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞攻击,因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。

举个例子,看看如何获取字符串的MD5值吧:

public class MD5Test {public static void main(String[] args) throws UnsupportedEncodingException {String s = "123";byte[] result = getMD5Bytes(s.getBytes());StringBuilder stringBuilder = new StringBuilder();for (byte temp : result) {if (temp >= 0 && temp < 16) {stringBuilder.append("0");}stringBuilder.append(Integer.toHexString(temp & 0xff));}System.out.println(s + ",MD5加密后:" + stringBuilder.toString());}private static byte[] getMD5Bytes(byte[] content) {try {MessageDigest md5 = MessageDigest.getInstance("MD5");return md5.digest(content);} catch (NoSuchAlgorithmException e) {throw new RuntimeException(e);}}
}

运行结果:

123,MD5加密后:202cb962ac59075b964b07152d234b70

4.1.2 ShA家族算法

SHA(Secure Hash Algorithm,安全散列算法),包括SHA-0、SHA-1、SHA-2(SHA-256,SHA-512,SHA-224,SHA-384等)、SHA-3。它是在MD算法基础上实现的,与MD算法区别在于「摘要长度」,SHA 算法的摘要「长度更长,安全性更高」。

SHA-0发布之后很快就被NSA撤回,因为含有会降低密码安全性的错误,它是SHA-1的前身。
SHA-1在许多安全协议中广为使用,包括TLS、GnuPG、SSH、S/MIME和IPsec,是MD5的后继者。
SHA-2包括SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。它的算法跟SHA-1基本上相似,目前还没有出现明显弱点。
SHA-3是2015年正式发布,由于对「MD5出现成功的破解」,以及对SHA-0和SHA-1出现理论上破解的方法,SHA-3应运而生。它与之前算法不同的是,它是可替换的加密散列算法。

SHA-1、SHA-2(SHA-256,SHA-512,SHA-224,SHA-384)等算法是比较常用的,我们来看看跟MD5的对比吧

算法类型摘要长度(bits)最大输入消息长度(bits)碰撞攻击(bits)性能示例(MiB/s)
MD5128无限≤18(发现碰撞)335
SHA-11602^64 − 1<63(发现碰撞)192
SHA-2242242^64 − 1112139
SHA-2562562^64 − 1128139
SHA-3843842^128 − 1192154
SHA-5125122^128 − 1256154

4.1.3 MAC算法家族

MAC算法 MAC(Message Authentication Code,消息认证码算法),是带密钥的Hash函数。输入密钥和消息,输出一个消息摘要。它集合了MD和SHA两大系列消息摘要算法。

  • MD 系列算法: HmacMD2、HmacMD4 和 HmacMD5 ; SHA
  • 系列算法:HmacSHA1、HmacSHA224、HmacSHA256、HmacSHA384 和 HmacSHA512 。

4.2 对称加密算法

加密和解密使用「相同密钥」的加密算法就是对称加密算法。常见的对称加密算法有AES、3DES、DES、RC5、RC6等。
在这里插入图片描述

4.2.1 DES

数据加密标准(英语:Data Encryption Standard,缩写为 DES)是一种对称密钥加密块密码算法。DES算法的入口参数有三个:Key、Data、Mode。

  • Key: 7个字节共56位,是DES算法的工作密钥;
  • Data: 8个字节64位,是要被加密或被解密的数据;
  • Mode: 加密或解密。

4.2.2 3DES

三重数据加密算法(英语:Triple Data Encryption Algorithm,又称3DES(Triple DES),是一种对称密钥加密块密码,相当于是对每个数据块应用三次数据加密标准(DES)算法。

4.2.3 AES

AES,高级加密标准(英语:Advanced Encryption Standard),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。

  • 采用对称分组密码体制,密钥长度为 128 位、 192 位、256 位,分组长度128位
  • 相对于DES ,AES具有更好的 安全性、效率 和 灵活性。

4.3 非对称加密算法

非对称加密算法需要两个密钥:公钥和私钥。公钥与私钥是成对存在的,如果用公钥对数据进行加密,只有用对应的私钥才能解密。主要的非对称加密算法有:RSA、Elgamal、DSA、D-H、ECC。
在这里插入图片描述

4.3.1 RSA算法

  • RSA加密算法是一种非对称加密算法,广泛应用于加密和数字签名
  • RSA算法原理:两个大素数的乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
  • RSA是被研究得最广泛的公钥算法,从提出到现在,经历了各种攻击的考验,普遍认为是目前最优秀的公钥方案之一。

4.3.2 DSA

  • DSA(Digital Signature Algorithm,数字签名算法),也是一种非对称加密算法。
  • DSA和RSA区别在,DSA仅用于数字签名,不能用于数据加密解密。其安全性和RSA相当,但其性能要比RSA好。

4.3.3 ECC 算法

  • ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学),基于椭圆曲线加密。
  • Ecc主要优势是,在某些情况下,它比其他的方法使用更小的密钥,比如RSA加密算法,提供相当的或更高等级的安全级别。
  • 它的一个缺点是,加密和解密操作的实现比其他机制时间长 (相比RSA算法,该算法对CPU 消耗严重)。

4.4 国密算法

国密即国家密码局认定的国产密码算法。为了保障商用密码的安全性,国家商用密码管理办公室制定了一系列密码标准,即SM1,SM2,SM3,SM4等国密算法。
在这里插入图片描述

4.4.1 SM1

  • SM1,为对称加密算法,加密强度为128位,基于硬件实现。
  • SM1的加密强度和性能,与AES相当。

4.4.2 SM2

  • SM2主要包括三部分:签名算法、密钥交换算法、加密算法
  • SM2用于替换RSA加密算法,基于ECC,效率较低。

4.4.3 SM3

  • SM3,即国产消息摘要算法。
  • 适用于商用密码应用中的数字签名和验证,消息认证码的生成与验证以及随机数的生成。

4.4.4 SM4

  • SM4是一个分组算法,用于无线局域网产品。
  • 该算法的分组长度为128比特,密钥长度为128比特。
  • 加密算法与密钥扩展算法都采用32轮非线性迭代结构。
  • 解密算法与加密算法的结构相同,只是轮密钥的使用顺序相反,解密轮密钥是加密轮密钥的逆序。
    它的功能类似国际算法的DES。

5 加签验签相关Java的API

这个小节先介绍一下加签验签需要用到的API吧~
在这里插入图片描述

5.1 加签相关API

- java.security.Signature.getInstance(String algorithm); //根据对应算法,初始化签名对象
- KeyFactory.getInstance(String algorithm);// 根据对应算法,生成KeyFactory对象
- KeyFactory.generatePrivate(KeySpec keySpec); //生成私钥
- java.security.Signature.initSign(PrivateKey privateKey) //由私钥,初始化加签对象
- java.security.Signature.update(byte[] data)  //把原始报文更新到加签对象
- java.security.Signature.sign();//加签
  • 「Signature.getInstance(String algorithm);」
    根据对应算法,初始化签名对象
    algorithm参数可以取SHA256WithRSA或者MD5WithRSA等参数,SHA256WithRSA表示生成摘要用的是SHA256算法,签名加签用的是RSA算法

  • 「KeyFactory.getInstance(String algorithm);」
    根据对应算法,生成KeyFactory对象,比如你的公私钥用的是RSA算法,那么就传入RSA

  • 「KeyFactory.generatePrivate(KeySpec keySpec)」
    生成私钥,加签用的是私钥哈,所以需要通过KeyFactory先构造一个私钥对象。

  • 「Signature.initSign(PrivateKey privateKey)」
    加签用的是私钥,所以传入私钥,初始化加签对象

  • 「Signature.update(byte[] data)」
    把原始报文更新到加签对象

  • 「java.security.Signature.sign();」
    进行加签操作

5.2 验签相关API

- java.security.Signature.getInstance(String algorithm); //根据对应算法,初始化签名对象
- KeyFactory.getInstance(String algorithm);// 根据对应算法,生成KeyFactory对象
- KeyFactory.generatePublic(KeySpec keySpec); //生成公钥
- java.security.Signature.initVerify(publicKey); //由公钥,初始化验签对象
- java.security.Signature.update(byte[] data)  //把原始报文更新到验签对象
- java.security.Signature.verify(byte[] signature);//验签
  • 「Signature.getInstance(String algorithm)」
    根据对应算法,初始化签名对象,注意验签和加签是需要用相同的algorithm算法参数哦~
  • 「KeyFactory.getInstance(String algorithm);」
    根据对应算法,生成KeyFactory对象
  • 「KeyFactory.generatePublic(KeySpec keySpec);」
    生成公钥,验签用的是公钥,通过KeyFactory先构造一个公钥对象
  • 「Signature.initVerify(publicKey);」
    公钥验签,所以传入公钥对象参数,初始化验签对象
  • 「Signature.update(byte[] data)」
    把原始报文更新到加签对象
  • 「Signature.verify(byte[] signature);」
    进行验签操作

6 加签验签代码实现

前几个小节讨论完概念,是时候上代码实战了,我这边用的是SHA-256作为摘要算法,RSA作为签名验签算法,如下:

package pattern;import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;/*** 加签验签demo*  @Author 捡田螺的小男孩*/
public class SignatureTest {//公钥字符串private static final String PUBLIC_KEY_STR = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaJzVjC5K6kbS2YE2fiDs6H8pB\n" +"JFDGEYqqJJC9I3E0Ebr5FsofdImV5eWdBSeADwcR9ppNbpORdZmcX6SipogKx9PX\n" +"5aAO4GPesroVeOs91xrLEGt/arteW8iSD+ZaGDUVV3+wcEdci/eCvFlc5PUuZJou\n" +"M2XZaDK4Fg2IRTfDXQIDAQAB";//私钥字符串private static final String PRIVATE_KEY_STR = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBANonNWMLkrqRtLZg\n" +"TZ+IOzofykEkUMYRiqokkL0jcTQRuvkWyh90iZXl5Z0FJ4APBxH2mk1uk5F1mZxf\n" +"pKKmiArH09floA7gY96yuhV46z3XGssQa39qu15byJIP5loYNRVXf7BwR1yL94K8\n" +"WVzk9S5kmi4zZdloMrgWDYhFN8NdAgMBAAECgYA9bz1Bn0i68b2KfqRdgOfs/nbe\n" +"0XNN1DLQp2t7WDfRCg01iI1zPkZgyFVZWtI85f5/uIrLs5ArLosL1oNuqqc0nNne\n" +"CvJK+ZxvA98Hx3ZqYTzDnleR054YhofL5awbhSciYVic204DOG1rhSsYWMqtX7J7\n" +"3geoWL7TYdMfYXcCAQJBAPMMKsz6ZJh98EeQ1tDG5gpAGWFQkYNrxZDelP/LjeO0\n" +"TP3XkQnIpcaZoCs7V/rRGRGMWwQ2BUdc/01in89ZZ5ECQQDlx2oBc1CtOAm2UAhN\n" +"1xWrPkZWENQ53wTrwXO4qbTGDfBKon0AehLlGCSqxQ71aufLkNO7ZlX0IHTAlnk1\n" +"TvENAkAGSEQ69CXxgx/Y2beTwfBkR2/gghKg0QJUUkyLqBlMz3ZGAXJwTE1sqr/n\n" +"HiuSAiGhwH0ByNuuEotO1sPGukrhAkAMK26a2w+nzPL+u+hkrwKPykGRZ1zGH+Cz\n" +"19AYNKzFXJGgclCqiMydY5T1knBDYUEbj/UW1Mmyn1FvrciHoUG1AkAEMEIuDauz\n" +"JabEAU08YmZw6OoDGsukRWaPfjOEiVhH88p00veM1R37nwhoDMGyEGXVeVzNPvk7\n" +"cELg28MSRzCK";public static void main(String[] args) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidKeySpecException {//原始报文String plain = "我是一个报文";//加签byte[] signatureByte = sign(plain);System.out.println("原始报文是:" + plain);System.out.println("加签结果:");System.out.println(new BASE64Encoder().encode(signatureByte));//验签boolean verifyResult = verify(plain, signatureByte);System.out.println("验签结果:" + verifyResult);}/*** 加签方法* @param plain* @return* @throws NoSuchAlgorithmException* @throws InvalidKeyException* @throws UnsupportedEncodingException* @throws SignatureException*/private static byte[] sign(String plain) throws NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException, SignatureException {//根据对应算法,获取签名对象实例Signature signature = Signature.getInstance("SHA256WithRSA");//获取私钥,加签用的是私钥,私钥一般是在配置文件里面读的,这里为了演示方便,根据私钥字符串生成私钥对象PrivateKey privateKey = getPriveteKey(PRIVATE_KEY_STR);//初始化签名对象signature.initSign(privateKey);//把原始报文更新到对象signature.update(plain.getBytes("UTF-8"));//加签return signature.sign();}/*** 验签方法* @param plain* @param signatureByte* @return* @throws NoSuchAlgorithmException* @throws InvalidKeyException* @throws IOException* @throws SignatureException* @throws InvalidKeySpecException*/private static boolean verify(String plain, byte[] signatureByte) throws NoSuchAlgorithmException, InvalidKeyException, IOException, SignatureException, InvalidKeySpecException {//获取公钥PublicKey publicKey = getPublicKey(PUBLIC_KEY_STR);//根据对应算法,获取签名对象实例Signature signature = Signature.getInstance("SHA256WithRSA");//初始化签名对象signature.initVerify(publicKey);//把原始报文更新到签名对象signature.update(plain.getBytes("UTF-8"));//进行验签return signature.verify(signatureByte);}private static PublicKey getPublicKey(String publicKeyStr) throws InvalidKeySpecException, IOException {PublicKey publicKey = null;try {java.security.spec.X509EncodedKeySpec bobPubKeySpec = new java.security.spec.X509EncodedKeySpec(new BASE64Decoder().decodeBuffer(publicKeyStr));// RSA对称加密算法java.security.KeyFactory keyFactory;keyFactory = java.security.KeyFactory.getInstance("RSA");// 生成公钥对象publicKey = keyFactory.generatePublic(bobPubKeySpec);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}return publicKey;}private static PrivateKey getPriveteKey(String privateKeyStr) {PrivateKey privateKey = null;PKCS8EncodedKeySpec priPKCS8;try {priPKCS8 = new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(privateKeyStr));KeyFactory keyf = KeyFactory.getInstance("RSA");privateKey = keyf.generatePrivate(priPKCS8);} catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException e) {e.printStackTrace();}return privateKey;}
}

http://www.ppmy.cn/news/426436.html

相关文章

一文了解数字签名、数字证书、自签证书

参考 关于自签SSL证书的一些小知识汇总 对于ssl中的pem文件和key 文件的理解 openssl 生成证书 ca.pem client.pem server.pem SSL&#xff1a;证书文件 数字证书原理 数字签名是什么&#xff1f; 数字签名和数字证书的原理解读(图文) 数字签名和数字证书有哪些区别与联…

【数字签名】如何正确地加签/验签

项目上需要用到数字签名&#xff0c;原本是简单的服务器签名&#xff0c;客户端验签的流程。因为ios端没有找到比较好的验签库&#xff0c;故根据网传的步骤实现验签&#xff0c;但死活验签不成功&#xff0c;折腾了半天。 网上的验签流程: 数字签名的技术流程描述如下&…

对签名验签的理解

1.公钥私钥 1.1一些规则&#xff1a; 公钥加密的数据只有私钥能解开私钥加密的数据只有公钥能解开公钥有很多把&#xff0c;私钥只有一把 注&#xff1a;无需知道原理&#xff0c;只要记住这么个规则 1.2这些规则产生的结论&#xff1a; 下面假设你有一把私钥和公钥&#x…

爱签电子合同怎么签,应该注意哪些问题?

随着在线办公趋势的发展&#xff0c;电子合同成为越来越多企业的选择&#xff0c;但相关法律对电子合同的有效性又有严格的规定&#xff0c;那么企业电子合同到底该怎么签&#xff0c;应该注意什么问题呢&#xff0c;今天就带大家了解一下。 根据人力资源社会保障部办公厅发布的…

国务院:推进电子印章、签名应用,君子签助推高频事项“跨省通办”

10月5日&#xff0c;国务院办公厅印发《关于加快推进政务服务“跨省通办”的指导意见》&#xff08;以下简称《指导意见》&#xff09;&#xff0c;明确指出&#xff1a;加快推进电子印章、电子签名应用和跨地区、跨部门互认&#xff0c;为提高“跨省通办”服务效能提供有效支撑…

签名验签

几个基本概念&#xff1a; 加密:发送方利用接收方的公钥对要发送的明文进行加密。 解密:接受方利用自己的私钥进行解密。 公钥和私钥配对的&#xff0c;用公钥加密的文件&#xff0c;只有对应的私钥才能解密。当然也可以反过来&#xff0c;用私钥加密&#xff0c;用对应的公…

电子签名的制作和使用

电子签名的制作和使用 一、在Word文档中插入手写签名生成电子签名1、准备好签名图片。2、用Word打开需要签名的文件&#xff0c;点菜单中的“插入>插图>图片”来选择已经写好的签名图片&#xff0c;插入后可以调整图片大小。3、点击菜单“格式>颜色>黑白”。4、点击…

电子签名-为你的数据签字画押

博主&#xff1a;爱码叔 个人博客站点&#xff1a; icodebook 公众号&#xff1a;漫话软件设计 专注于软件设计与架构、技术管理。擅长用通俗易懂的语言讲解技术。对技术管理工作有自己的一定见解。文章会第一时间首发在个站上&#xff0c;欢迎大家关注访问&#xff01; 更多密…