1. JWT介绍

在介绍JWT之前先看一下传统校验令牌的方法,如下图:

传统校验

问题:
传统授权方法的问题是用户每次请求资源服务,资源服务都需要携带令牌访问认证服务去校验令牌的合法性,并根据令牌获取用户的相关信息,性能低下。

解决:
使用JWT的思路是,用户认证通过会得到一个JWT令牌,JWT令牌中已经包括了用户相关的信息,客户端只需要携带JWT访问资源服务,资源服务根据事先约定的算法自行完成令牌校验,无需每次都请求认证服务完成授权。

JWT令牌授权过程如下图:

JWT校验

什么是JWT?
JSON Web Token(JWT)是一个开放的行业标准(RFC 7519),它定义了一种简介的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或使用RSA的公 钥/私钥对来签名,防止被篡改。

JWT令牌的优点:

  • jwt基于json,非常方便解析。
  • 可以在令牌中自定义丰富的内容,易扩展。
  • 通过非对称加密算法及数字签名技术,JWT防止篡改,安全性高。
  • 资源服务使用JWT可不依赖认证服务即可完成授权。

缺点:

  • JWT令牌较长,占存储空间比较大。

2.JWT的使用场景主要包括:

认证授权
这是比较常见的使用场景,只要用户登录过一次系统,之后的请求都会包含签名出来的token,通过token也可以用来实现单点登录。
因为它的开销很小,并且能够在不同的域中轻松使用。
交换信息
JSON Web令牌是在各方之间安全传输信息的好方法。因为JWT可以签名 - 例如,使用公钥/私钥对 - 您可以确定发件人是他们所说的人。此外,由于使用标头和有效负载计算签名,您还可以验证内容是否未被篡改。

3.无状态登录

目前我们创建了若干个微服务,假如我们在用户中心做了登陆,接下来要去商品详情页添加商品,此时就要跳转到购物车微服务,但是购物车微服务和用户微服务不是同一台tomcat,之前判断登录状态是通过tomcat session ,通过保存用户信息到tomcat session 中,那现在我们有两台不同的tomcat,所以现在跳转之后没有登录状态了,这显然是不合理的,因为用户信息无法共享,所以之前所学的登录在分布式系统中是没法使用的,那我们就来解决这个问题——无状态登录。

3.1 有状态登录

有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session。

例如登录:用户登录后,我们把登录者的信息保存在服务端session中,并且给用户一个cookie值,记录对应的session。然后下次请求,用户携带cookie值来,我们就能识别到对应session,从而找到用户的信息。

缺点

  • 服务端保存大量数据,增加服务端压力
  • 服务端保存用户状态,无法进行水平扩展
  • 客户端请求依赖服务端,多次请求必须访问同一台服务器

#####3.2 无状态登陆
微服务集群中的每个服务,对外提供的都是Rest风格的接口。而Rest风格的一个最重要的规范就是:服务的无状态性,即:

  • 服务端不保存任何客户端请求者信息
  • 客户端的每次请求必须具备自描述信息,通过这些信息识别客户端身份(并不是用户说自己是谁就是谁,自描述信息会在服务端生成)

带来的好处是什么呢?

  • 客户端请求不依赖服务端的信息,任何多次请求不需要必须访问到同一台服务
  • 服务端的集群和状态对客户端透明
  • 服务端可以任意的迁移和伸缩
  • 减小服务端存储压力
3.3 如何实现无状态

无状态登录的流程:

  1. 当客户端第一次请求服务时,服务端对用户进行信息认证(登录)
  2. 认证通过,将用户信息进行加密形成token,返回给客户端,作为登录凭证
  3. 以后每次请求,客户端都携带认证的token
  4. 服务的对token进行解密,判断是否有效。

流程图:

流程图

整个登录过程中,最关键的点是什么?

token的安全性

token是识别客户端身份的唯一标示,如果加密不够严密,被人伪造那就完蛋了。

采用何种方式加密才是安全可靠的呢?

我们将采用JWT + RSA非对称加密与JWT + HS256(安全程度没前者高,推荐前者)

4.JWT 的组成结构

实际的 jwt 产生的token,大概长得如下的格式

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJzdWIiOiJ0ZXN0IiwiYXVkIjpbImFwcCIsIndlYiJdLCJkYXRhIjoie1wiYWdlXCI6MjQsXCJzZXhcIjoxLFwidXNlcklkXCI6MSxcInVzZXJuYW1lXCI6XCLluIXlpKflj5RcIn0iLCJpc3MiOiJyc3R5cm8iLCJleHAiOjE1NTUzOTg5NjIsImlhdCI6MTU1NTM5ODg0Mn0.
N1PbxQ1okvw-q8TWiSX0uMx1z6QL6IEUBtOfcwP7-Mg

它是一个很长的字符串,中间用点(.)分隔成三个部分。

  • Header(头部)
  • Payload(负载)
  • Signature(签名)

1、Header(头部)
标头通常由两部分组成:令牌的类型,即JWT,以及正在使用的签名算法,例如HMAC SHA256或RSA。
例如:

1
2
3
4
{
"alg": "HS256",
"typ": "JWT"
}

然后,这个JSON被编码为Base64Url,形成JWT的第一部分。

2、Payload(负载)
令牌的第二部分是有效负载,其中包含声明。声明是关于实体(通常是用户)和其他数据的声明
这个部分一般就是我们需要存贮的数据都放在这里。
JWT 规定了7个官方字段,供选用。

  1. iss (issuer):发布者
  2. sub (subject):主题
  3. iat (Issued At):生成签名的时间
  4. exp (expiration time):签名过期时间
  5. aud (audience):观众,相当于接受者
  6. nbf (Not Before):生效时间
  7. jti (JWT ID):编号

当然,也可以自定义字段,例如下面的** data** 字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"sub": "test",
"aud": [
"app",
"web"
],
"nbf": 1555399851,
"data": "{\"age\":23,\"sex\":1,\"userId\":1,\"username\":\"张鑫\"}",
"iss": "rstyro",
"exp": 1555399971,
"iat": 1555399851,
"jti": "75f67651-4cc8-431a-9429-c15df52d5acd"
}

然后经过Base64Url编码,形成JSON Web令牌的第二部分

3、Signature(签名)
Signature 部分是对前两部分的签名,防止数据篡改。
首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名

1
2
3
4
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用”点”(.)分隔,就可以返回给用户。

4、Base64URL
前面提到,Header 和 Payload 串型化的算法是 Base64URL。这个算法跟 Base64 算法基本类似,但有一些小的不同。

JWT 作为一个令牌token,有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_ 。这就是 Base64URL 算法

4.1JWT交互流程

流程图:

交互流程

步骤翻译:

  1. 用户登录
  2. 服务的认证,通过后根据secret生成token
  3. 将生成的token返回给用户
  4. 用户每次请求携带token
  5. 服务端利用公钥解读jwt签名,判断签名有效后,从Payload中获取用户信息
  6. 处理请求,返回响应结果

因为JWT签发的token中已经包含了用户的身份信息,并且每次请求都会携带,这样服务端就无需保存用户信息,甚至无需去数据库查询,完全符合了Rest的无状态规范。

5.JWT 的加密方式

    JWT签名算法中,一般有两个选择,一个采用HS256,另外一个就是采用RS256
    签名实际上是一个加密的过程,生成一段标识(也是JWT的一部分)作为接收方验证信息是否被篡改的依据。
    RS256 (采用SHA-256RSA 签名) 是一种非对称算法, 它使用公共/私钥对: 标识提供方采用私钥生成签名, JWT 的使用方获取公钥以验证签名。由于公钥 (与私钥相比) 不需要保护, 因此大多数标识提供方使其易于使用方获取和使用 (通常通过一个元数据URL)。
    另一方面, HS256 (带有 SHA-256 的 HMAC 是一种对称算法, 双方之间仅共享一个 密钥。由于使用相同的密钥生成签名和验证签名, 因此必须注意确保密钥不被泄密。
    在开发应用的时候启用JWT,使用RS256更加安全,你可以控制谁能使用什么类型的密钥。另外,如果你无法控制客户端,无法做到密钥的完全保密,RS256会是个更佳的选择,JWT的使用方只需要知道公钥。
    由于公钥通常可以从元数据URL节点获得,因此可以对客户端进行进行编程以自动检索公钥。如果采用这种方式,从服务器上直接下载公钥信息,可以有效的减少配置信息

6.JWT 代码实现(HS256 方式)

JSON Web Tokens官网 Libraries里有各种语言的推荐包
https://github.com/jwtk/jjwt JWT官网里面star最多的,所以用了

6.1导入依赖

1
2
3
4
5
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>

6.2生成Token(采用HS256)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
public void createJWT(){
//我们将用于签署令牌的JWT签名算法
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
//创建时间
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
//让我们设置JWT Claims
JwtBuilder builder = Jwts.builder().setId("1231231312")
.setIssuedAt(now)
.setSubject("JWT令牌测试")
.setIssuer("zhangxin")
.signWith(signatureAlgorithm, "signingKey");
builder.claim("name", "自定义信息"); //设置自定义的信息
//构建JWT并将其序列化为紧凑的URL安全字符串
System.out.println(builder.compact());

}

6.3 解析token

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 @Test
public void parseToken(){
String token="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxMjMxMjMxMzEyIiwiaWF0IjoxNTg0MDcwODkyLCJzdWIiOiJKV1Tku6TniYzmtYvor5UiLCJpc3MiOiJ6aGFuZ3hpbiIsIm5hbWUiOiLoh6rlrprkuYnkv6Hmga8ifQ.V6YpKe2jFL-zveST7Gda1e4inZIhCU4mL54tZNBtXxc";
Claims claims = Jwts.parser()
.setSigningKey("signingKey")
.parseClaimsJws(token).getBody();
System.out.println(claims.toString());
System.out.println("ID: " + claims.getId());
System.out.println("Subject: " + claims.getSubject());
System.out.println("Issuer: " + claims.getIssuer());
System.out.println("Expiration: " + claims.getExpiration());


}

控制台结果

1
2
3
4
5
6
{jti=1231231312, iat=1584070892, sub=JWT令牌测试, iss=zhangxin, name=自定义信息}
ID: 1231231312
Subject: JWT令牌测试
Issuer: zhangxin
Expiration: null

7.基于私钥生成jwt令牌(RSA方式)

Spring Security 提供对JWT的支持,本节我们使用Spring Security 提供的JwtHelper来创建JWT令牌,校验JWT令牌等操作。
JWT令牌生成采用非对称加密算法

1、生成密钥证书
下边命令生成密钥证书,采用RSA 算法每个证书包含公钥和私钥

1
keytool -genkeypair -alias xckey -keyalg RSA -keypass xuecheng -keystore xc.keystore -storepass xuechengkeystore
  • Keytool 是一个java提供的证书管理工具
  • alias:密钥的别名
  • keyalg:使用的hash算法
  • keypass:密钥的访问密码
  • keystore:密钥库文件名,xc.keystore保存了生成的证书
  • storepass:密钥库的访问密码

Keytool 是一个java提供的证书管理工具

查询证书信息:

1
keytool -list -keystore xc.keystore

删除别名

1
keytool -delete -alias xckey -keystore xc.keystore

2、导出公钥
openssl是一个加解密工具包,这里使用openssl来导出公钥信息。

安装 openssl:http://slproweb.com/products/Win32OpenSSL.html
安装资料目录下的Win64OpenSSL-1_1_0g.exe
配置openssl的path环境变量,本教程配置在D:\OpenSSL-Win64\bin,cmd进入xc.keystore文件所在目录执行如下命令:

1
keytool -list -rfc --keystore xc.keystore | openssl x509 -inform pem -pubkey

公私钥匙

下边这一段就是公钥内容:

1
2
3
4
5
6
7
8
9
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApRJc3QAgJNV4CwPWQ85/
ZCzj0tm00abvz/EKrh4/NyyXxxyfWSszEYthBWZ07c8yzF4/zfl++3D1MLVokjTA
c9gczvF2xgMVdf/AL2gHKQMYNxYFC2kW1znRXmM1WUT5gy1lx0R2z9+zEpt8QOI2
16emV3Rz1e8iEvD9LBcIi3yFLGxdRqBVjJxyCbCsjpcxVj9gNQpve3566LFtJSMD
NCy0NM0zCNb9+cUKr0fOpEXeK34Qr0XbcvBgb8VQn+4U9GQuqVhNBHOCbDMIAuEk
FUXrUnhke/ApvIa9mqyqpQS1CuJ9562Al5OJW5CE8a5twiuxj5+/Z3Bc4TnOpeV4
jwIDAQAB
-----END PUBLIC KEY-----

将上边的公钥拷贝到文本文件中,合并为一行!!!

导入Pom依赖

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>

dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>

7.2生成jwt令牌

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
@Test
public void testCreateJWT() {
//证书文件
String key_location = "xc.keystore";
//密钥密码
String keystore_password = "xuechengkeystore";
//访问证书路径
ClassPathResource classPathResource = new ClassPathResource(key_location);
//密钥工厂
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(classPathResource, keystore_password.toCharArray());
//密钥的密码,此时密码和别名要匹配
String keypassword = "xuecheng";
//密钥别名
String alias = "xckey";
//密钥对(公钥和私钥)
KeyPair keyPair = keyStoreKeyFactory.getKeyPair(alias, keypassword.toCharArray());
//私钥
RSAPrivateKey aPrivate = (RSAPrivateKey) keyPair.getPrivate();
HashMap<String, Object> tokenMap = new HashMap<>();
tokenMap.put("id", "123");
tokenMap.put("name", "zhangxin");
tokenMap.put("roles", "程序员");
tokenMap.put("sex", "男");
//生成JWT令牌
Jwt jwt = JwtHelper.encode(JSON.toJSONString(tokenMap), new RsaSigner(aPrivate));
//取出JWT令牌
String token = jwt.getEncoded();
System.out.println("token=" + token);
}

7.3解析jwt令牌

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

@Test
public void testVerify(){
//JWT令牌
String token="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlcyI6Iueoi-W6j-WRmCIsInNleCI6IueUtyIsIm5hbWUiOiJ6aGFuZ3hpbiIsImlkIjoiMTIzIn0.LxAVaatS4ffSU1adFnjHTX8ghoolYg_K_cJ3w60vK5NRal2asZbUMY0k7sS2r_nD5YR7eoWLgHmHWOR73HsqpnIlODT0TTfspizksmNpyJLFHn79E9y6_QCB-Lkcmp4oq6VElXgJH4FlZigSOM_VwOMMtV5ZMLeWRlA-YhmgDquuo1_S8YN3L6hPfoHXPGzI_hqz2h2cECCH-DZNj8wVgZRZYS7iA6g6zqBrhkOmcy6B-a7p4QaAIBs8eHpIYsw1tEb3A_tJFAotpr1ztYF-5cMdvvUqmA5m4qppDdYi8HbMnZhuy9KKw2KGm_FAR777wTDKruN4ioMD-Nvn7qBEYA";
//公钥
String publicKey="-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnASXh9oSvLRLxk901HANYM6KcYMzX8vFPnH/To2R+SrUVw1O9rEX6m1+rIaMzrEKPm12qPjVq3HMXDbRdUaJEXsB7NgGrAhepYAdJnYMizdltLdGsbfyjITUCOvzZ/QgM1M4INPMD+Ce859xse06jnOkCUzinZmasxrmgNV3Db1GtpyHIiGVUY0lSO1Frr9m5dpemylaT0BV3UwTQWVW9ljm6yR3dBncOdDENumT5tGbaDVyClV0FEB1XdSKd7VjiDCDbUAUbDTG1fm3K9sx7kO1uMGElbXLgMfboJ963HEJcU01km7BmFntqI5liyKheX+HBUCD4zbYNPw236U+7QIDAQAB-----END PUBLIC KEY-----";
//校验JWT
Jwt jwt = JwtHelper.decodeAndVerify(token, new RsaVerifier(publicKey));
//获取原始内容
String claims = jwt.getClaims();
//JWT令牌
String encoded = jwt.getEncoded();
System.out.println(claims.toString());
System.out.println(encoded);
}

运行结果

1
2
3
{"roles":"程序员","sex":"男","name":"zhangxin","id":"123"}
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlcyI6Iueoi-W6j-WRmCIsInNleCI6IueUtyIsIm5hbWUiOiJ6aGFuZ3hpbiIsImlkIjoiMTIzIn0.LxAVaatS4ffSU1adFnjHTX8ghoolYg_K_cJ3w60vK5NRal2asZbUMY0k7sS2r_nD5YR7eoWLgHmHWOR73HsqpnIlODT0TTfspizksmNpyJLFHn79E9y6_QCB-Lkcmp4oq6VElXgJH4FlZigSOM_VwOMMtV5ZMLeWRlA-YhmgDquuo1_S8YN3L6hPfoHXPGzI_hqz2h2cECCH-DZNj8wVgZRZYS7iA6g6zqBrhkOmcy6B-a7p4QaAIBs8eHpIYsw1tEb3A_tJFAotpr1ztYF-5cMdvvUqmA5m4qppDdYi8HbMnZhuy9KKw2KGm_FAR777wTDKruN4ioMD-Nvn7qBEYA

8.RSA加密

8.1 加密技术

加密技术是对信息进行编码和解码的技术,编码是把原来可读信息(又称明文)译成代码形式(又称密文),其逆过程就是解码(解密),加密技术的要点是加密算法,加密算法可以分为三类:

  • 对称加密,如AES
    • 基本原理:将明文分成N个组,然后使用密钥对各个组进行加密,形成各自的密文,最后把所有的分组密文进行合并,形成最终的密文。
    • 优势:算法公开、计算量小、加密速度快、加密效率高
    • 缺陷:双方都使用同样密钥,安全性得不到保证
  • 非对称加密,如RSA
    • 基本原理:同时生成两把密钥:私钥和公钥,私钥隐秘保存,公钥可以下发给信任客户端
    • 私钥加密,持有私钥或公钥才可以解密
    • 公钥加密,持有私钥才可解密
    • 优点:安全,难以破解
    • 缺点:算法比较耗时
  • 不可逆加密,如MD5,SHA
    • 基本原理:加密过程中不需要使用密钥,输入明文后由系统直接经过加密算法处理成密文,这种加密后的数据是无法被解密的,无法根据密文推算出明文。

8.2 没有RSA加密3

传统校验

注:我们把Zuul加进来,因为Zuul是整个后台微服务的入口,所有的请求都要先经过Zuul才能到达特定的微服务,所以我们关于鉴权的流程没有必要放在每一个微服务做一次,这就太复杂了,我们放在入口Zuul的位置,只需要做一次。

  1. 用户请求登录
  2. Zuul将请求转发到授权中心,请求授权
  3. 授权中心校验完成,颁发JWT凭证
  4. 客户端请求其它功能,携带JWT
  5. Zuul将JWT交给授权中心校验,通过后放行
  6. 用户请求到达微服务
  7. 微服务将JWT交给鉴权中心,鉴权同时解析用户信息
  8. 鉴权中心返回用户数据给微服务
  9. 微服务处理请求,返回响应

发现什么问题了?
每次鉴权都需要访问鉴权中心,系统间的网络请求频率过高,效率略差,鉴权中心的压力较大。

8.3 RSA加密

RSA加密

  1. 我们首先利用RSA生成公钥和私钥。私钥保存在授权中心,公钥保存在Zuul和各个微服务
  2. 用户请求登录
  3. 授权中心校验,通过后用私钥对JWT进行签名加密
  4. 返回JWT给用户
  5. 用户携带JWT访问
  6. Zuul直接通过公钥解密JWT,进行验证,验证通过则放行
  7. 请求到达微服务,微服务直接用公钥解析JWT,获取用户信息,无需访问授权中心

9. JWT 的特点

互联网服务中的用户认证方式 有两种:
SessionId
比如,用户在浏览器中用户名密码登录成功之后,浏览器每次发请求都会自己带上sessionid 发送给服务器。服务器通过sessionID 得到用户信息
TOKEN
token,一般在手机app 端比较常用的方式,那就是用户登录成功之后,服务器返回一个 授权的token 字符串,app 每次请求也要带着这个token 转到服务器,服务器通过 token 得到用户信息
如上两种方式都很类似,换汤不换药。它们的相同点就是:认证信息都保存在后端服务器
而JWT 和 它们的区别就是:认证信息保存在了客户端,减轻服务端的内存压力。

9.1特点

  • JWT是无状态的,特别适用于分布式站点的单点登录(SSO)场景
  • JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
  • 因为有签名,所以JWT可以防止被篡改
  • 由于JWT的payload是使用base64编码的,并没有加密,因此JWT中不能存储敏感数据。而session的信息是存在服务端的,相对来说更安全。
  • 由于是无状态使用JWT,所有的数据都被放到JWT里,如果还要进行一些数据交换,那载荷会很大,经过编码之后导致JWT非常长
  • JWT是一次性的。想修改里面的内容,就必须签发一个新的JWT
  • 一旦签发一个JWT,在到期之前就会始终有效,无法中途废弃。

RSA公钥和私钥是什么?

首先来说,RSA是一种非对称加密算法,它是由三位数学家(Rivest、Shamir、Adleman)设计出来的。非对称加密是相对于对称加密而言的。对称加密算法是指加密解密使用的是同一个秘钥,而非对称加密是由两个密钥(公钥、私钥)来进行加密解密的,由此可见非对称加密安全性更高。

公钥顾名思义就是公开的密钥会发放给多个持有人,而私钥是私有密码往往只有一个持有人。

公私钥特性

  • 公钥与私钥是成对出现的;

  • 私钥文件中包含了公钥数据,所以可以基于私钥导出公钥;

  • 密钥越长,越难破解,所以2048位密钥比1024位密钥要更安全;

  • 公钥和私钥都是密钥,被公开的那个就是公钥,没有被公开的那个就是私钥。

公钥和私钥都可用于加密和解密

公钥和私钥都可以用于加解密操作,用公钥加密的数据只能由对应的私钥解密,反之亦然。虽说两者都可用于加密,但是不同场景使用不同的密钥来加密,规则如下:

1、私钥用于签名、公钥用于验签

签名和加密作用不同,签名并不是为了保密,而是为了保证这个签名是由特定的某个人签名的,而不是被其它人伪造的签名,所以私钥的私有性就适合用在签名用途上。

私钥签名后,只能由对应的公钥解密,公钥又是公开的(很多人可持有),所以这些人拿着公钥来解密,解密成功后就能判断出是持有私钥的人做的签名,验证了身份合法性。

2、公钥用于加密、私钥用于解密,这才能起到加密作用

因为公钥是公开的,很多人可以持有公钥。若用私钥加密,那所有持有公钥的人都可以进行解密,这是不安全的!

若用公钥加密,那只能由私钥解密,而私钥是私有不公开的,只能由特定的私钥持有人解密,保证的数据的安全性。