在本篇博客中,我将向你介绍JWE身份验证以及如何加密和解密敏感数据。在指出JWE之前,让我们简要介绍一下它的父对象JWT。
介绍
JSON Web Token(JWT)用作在两个不同或多个地方(例如:客户端/服务器)之间传输敏感数据的容器。这些信息可以得到验证和信任,因为它是数字签名的。JWT可以使用密钥(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。
主要可以使用JWT来:
授权:这是JWT的主要责任。一旦用户登录,每个后续请求都将包括JWT,允许用户访问使用该令牌允许的路由、服务和资源。
信息交换:JWT是在多个方之间交换安全数据的更好方法。因为JWT有2个选项。一个是使用私钥/公钥签名有效载荷,另一个是加密有效载荷。
JWT本身不存在,它必须是JWS或JWE(JSON Web Encryption)之一。就像一个抽象类。JWS和JWE是具体的实现。简单来说,JWT是JWS和JWE的父类。
JWE vs JWS
之前我写过一篇关于JWS的博客文章。请访问这个使用HandlerInterceptor的Springboot REST API应用程序的JWT(JWS)身份验证 来了解JWS的行为和实现。现在让我们转向JWE!
什么是JWE(JSON Web Encryption)?
JSON Web Encryption(JWE)是一种使用JSON数据结构表示加密内容的方法。
JWE令牌由五个关键组件构成,每个组件由句点(.)分隔:JOSE标头、JWE加密密钥、JWE初始化向量、JWE附加认证数据(AAD)、JWE密文和JWE认证标记。
具有组件的JWE结构
让我们逐一查看一下。
JOSE标头
JOSE标头是JWE令牌的第一个元素,代表JSON对象签名和加密。JWE规范引入了许多标头参数。这里我提到了一些突出的标头元素。
alg:(必需)定义用于加密内容加密密钥(CEK)的算法。这必须设置为“RSA-OAEP”。
enc:(必需)定义用于对有效载荷执行身份验证加密以生成密文和身份验证标记的算法。这必须设置为“A128CBC-HS256”。
cty:(必需)定义有效负载的“内容类型”。在这种情况下,值必须为“JWT”,以指示在此JWT中携带了一个嵌套的JWT(=我们的JWS)。
kid:(可选)它是一个提示,指示用于保护JWE的密钥。 “kid”值的结构未指定。密钥提示引用用于加密JWE的公钥;这可用于确定解密JWE所需的私钥。
zip:(可选)如果需要令牌压缩,则必须按照zip标头元素下定义的压缩算法压缩明文JSON负载。
JWE加密密钥
内容加密密钥(CEK)使用预期接收者的密钥进行加密,生成的加密内容记录为字节数组,称为JWE加密密钥。该过程是JOSE标头定义了enc元素(内容加密算法)和alg(加密算法)以加密内容加密密钥(CEK)。例如:{“alg”:“RSA-OAEP”,“enc”:“A256GCM”}
JWE初始化向量
初始化向量用于在加密过程中引入随机性。一些用于内容加密的加密算法在加密过程中需要初始化向量。初始化向量是随机生成的数字,与密钥一起用于加密数据。
密文
密文本身是加密的有效负载。这意味着明文JSON有效负载。 JWE密文是通过使用Content Encryption Key(CEK)、JWE初始化向量和Additional Authentication Data(AAD)值,使用头元素enc定义的加密算法,对明文JSON有效负载进行加密计算的。
JWE认证标记
认证标记用于完整性检查。
现在我们对JWE令牌的组件有了一个总体了解。让我们看一个代码示例。请注意,在本博客文章中,我将向你展示如何生成JWE令牌并解密值。请参考我的先前文章有关JWS的完整实现(包括控制器/服务层更改/验证等)。你可以使用相同的方法使用JWE令牌对应用程序进行身份验证。
请访问此bitbucket URL以查看完整的JWE实现示例。
步骤1:创建KeyPair对象
首先,我们需要初始化KeyPairGenerator对象并定义密钥大小(2048字节)。然后,我们可以生成一个KeyPair对象来调用'genKeyPair()'方法。
步骤2:创建KeyFactory和RSA Keys Specs
这里我们需要先创建'KeyFactory'对象,调用'getInstance()'方法并将RSA算法作为参数。下一步将创建RSAPublicKeySpec和RSAPrivateKeySpec。为此,我们必须使用KeyFactory类中的'getKeySpec()'方法。参数将是,key:密钥。keySpec:应返回密钥材料的规范类。
步骤3:使用密钥规范从KeyFactory生成(和检索)RSA密钥
要生成RSAPublicKey / RSAPrivateKey,我们必须在KeyFactory类中分别使用称为'publicKeySpec','privateKeySpec'的参数调用'generatePublic'方法和'generatePrivate'方法。
请注意,当我们进行实际项目工作时,我们不会每次生成公钥和私钥。我们可以将它们保存在安全的S3桶或**AWS Secret Manager(推荐)**中。
注意:如果你使用'PublicKey'和'PrivateKey'对象,则必须将它们从RSAPublicKey和RSAPrivateKey分别转换。
步骤4:设置声明值。
我们需要使用JWTClaimsSet类中定义的builder()方法创建一个实例。JWTClaimsSet类提供了默认的声明值,例如,issuer,subject,expirationTime,notBeforeTime,jwtID。它还提供了添加自定义值的功能。你可以使用“claim(key,value)”方法设置自定义值。这就像Java java.utill.Map一样。
步骤5:创建JWE标头并将RSA-OAEP指定为加密算法,将128位AES / GCM指定为加密方法
步骤6:使用指定的公共RSA密钥创建RSA加密,并生成JWE令牌。
现在让我们看看如何解密和提取令牌声明值。
步骤1:将JWE字符串值转换为EncryptedJWT类型。
步骤2:使用指定的私有RSA密钥创建解密器。
步骤3:执行解密。
步骤4:提取敏感数据。
正如我在上面的示例中提到的,你可以使用键提取值(这非常类似于访问java.utill.Map键/值)。
请从此处查看完整版本,并在注释部分中解释了每个可能的步骤。如果你有疑虑或问题,请留下评论。抱歉,我不知道你想让我翻译什么,请提供更多的上下文信息。
译自:https://medium.com/aeturnuminc/encrypt-and-decrypt-sensitive-data-with-jwe-70421722f7e5
评论(0)