在采用轻量级移动设备的推动下,基于REST的通信的采用日益广泛,因此需要保护这些通信。 当消息包含信息有效负载时,尤其如此,通常将其格式化为JavaScript Object Notation(JSON)文本。
本文演示了如何使用运行6.0.1.0版或更高版本固件的WebSphere DataPower设备来加密JSON有效负载,以便使用REST标准进行传输。 这样可以保护与传输方法(例如SSL)无关的消息私密性。 我们将演示以下方法:
传输的加密(或发送)端和传输的解密(或接收)端均在此进行了说明。
本文还演示了如何使用XQuery和JSONiq处理脚本来执行加密和解密。
您可以在传输的发送和接收端使用相同的多协议网关服务; 静态后端目标只需要调整。
本文使用加密密钥和证书。 为了不间断地完成这些说明,您必须首先创建加密密钥和证书对象。
请按照以下说明创建必要的密钥和证书对象:
Ident
。 Jason
,如图1所示。 Jason
。 Jason
。 Shared
。 aes-128
,如图2所示。您必须使用此名称。 这是本文使用的示例JSON文档:
{
"Name":"Cartoon Studios",
"AccountID":"8458jf8757275234",
"Social-no":"123-45-6789",
"State":"MA"
}
通过执行本文中的步骤,可以确保“ Social-no”元素的值。
本文中创建的服务使用的目的地仅返回服务发送的内容,就像镜像一样。 要创建这样的目的地,请按照下列步骤操作:
HTTP
。 从出现的列表中选择HTTP服务 。 Mirror
。 2049
。 完成此处描述的每个处理规则后,您可以通过向网关发送请求来测试新规则。
要测试加密规则,请将纯JSON有效负载request.jsn发送到网关。 例如,这是curl命令:
curl –data-binary @request.jsn http://dp_addr:3333/ssn
要测试解密规则,首先需要创建一个加密的有效负载。 您可以通过捕获加密规则的输出来做到这一点。 这是使用curl的示例:
curl –data-binary @request.jsn http://dp_addr:3333/ssn > request-enc.jsn
curl –data-binary @request-enc.jsn http://dp_addr:3333/dssn
将应用程序域系统日志级别设置为“调试”,以捕获默认系统日志中的所有可能的调试条目。 为此,请单击控制面板上的“ 故障排除”图标。 在“ 日志记录”下 ,从“ 日志级别”下拉列表中选择“ 调试 ”。 然后单击“ 日志级别”按钮。
此处演示的所有方法都使用多协议网关服务来完成工作。 本节介绍此服务的配置(图3),除了“处理策略”。
Multi
。 SecureJSON
http://127.0.0.1:2049
: http://127.0.0.1:2049
: http://127.0.0.1:2049
HTTP3333
3333
此处详细介绍了将加密应用于JSON有效负载的三种方法。 您可能只想执行与要使用的方法有关的那些步骤。
请注意,网关配置使用非XML的请求类型来允许PKCS#7解密规则成功运行。 如果您不打算使用此规则,则可以将网关配置请求类型设置为JSON 。 这会使设备自动检查请求文档,以确保文档格式正确。 这对于探针也更有效。
SecureJSON
作为策略的名称 ,如图6所示。 SecureJSON_rule_pk7encrypt
。 ebin
,如图7所示。 */ebin
。 当您向该规则提交样本请求文档时,您应该收到与以下内容相似的结果:
---BEGIN PKCS7-----
MIIByQYJKoZIhvcNAQcDoIIBujCCAbYCAQAxgeAwgd0CAQAwRjA6MQswCQYDVQQG
EwJVUzELMAkGA1UECBMCTUExDjAMBgNVBAcTBUtUb3duMQ4wDAYDVQQDEwVKYXNv
bgIIBImBLUcGRo8wDQYJKoZIhvcNAQEBBQAEgYCHrd/qNEtgGZpXDK8yFLP65lO2
yRVtIst3E/hOqFy4Jt2YWtfsjLP2nuL27fEv3C+iLQSQo5leJCBaWF83xqUb4rMA
I+1/8+T19ciEm5u7JhPAJ17G2Ypd1jqquXeVeJq6Mo1jYqTKjMt+2ir8ijhhuX6/
JzOIa+cAznBOD4+uaDCBzQYJKoZIhvcNAQcBMB0GCWCGSAFlAwQBAgQQ2LCVsgxa
6alYZyGem0he2oCBoDbUr0nPULErHNfrk2twhBaPZzae3KUF07RYddamwBWBRkJe
7/Z4QU9WR8n/GoPe0vq6gsxHAaGqWCBoI0HCY+YTV6aF7ARlg5n2bVHKEx8lsH6G
fxWwoKJu6j/BSmJCcoYaJNc5fATxr8mFKMJV1GcQg666hwzx143GkcAHmaclXu9w
awpqndNhpKAukj6vxWUU8aAr8AehRRYaFXWoYf4=
-----END PKCS7-----
整个有效负载已加密。 将此结果保存在本地文件中,以提交解密此有效负载的规则,这将在下一部分中进行描述。
SecureJSON_rule_pk7decrypt
。 dbin
,如图12所示。 */dbin
。 如果提交上面构造的用于加密JSON有效负载的规则的结果,则应该再次收到原始的纯文本JSON文档。
{
"Name":"Cartoon Studios",
"AccountID":"8458jf8757275234",
"Social-no":"123-45-6789",
"State":"MA"
}
您必须创建一个共享密钥加密对象才能使用此方法。 如果尚未创建共享密钥,请按照“ 共享密钥”部分中的说明进行操作。
请按照以下步骤使用共享密钥来加密JSON有效内容的元素:
SecureJSON_rule_ssencrypt.
ssn
。 */ssn
。 这是set-dp-var.xq文件的内容:
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace dp = "http://www.datapower.com/extensions";
declare option jsoniq-version "0.4.42";
declare option output:method "json";
let $ssn := .("Social-no")
let $dono := dp:set-variable("var://context/mine/myvar1", $ssn)
let $myvar := dp:variable("var://context/mine/myvar1")
return
jn:object(
for $key in jn:keys(.)
let $val := if ($key = "Social-no") then $myvar else .($key)
return { $key : $val }
)
该脚本从提交的消息中提取Social-no JSON元素的值,将其放在DataPower变量中,然后使用相同的变量再次输出消息。 此转换的输出并不重要; 最重要的是DataPower变量的设置。 在处理策略的下一步中使用此变量。
此样式表检索上一步中设置的DataPower变量的值,使用共享密钥对其进行加密,然后将结果放入DataPower变量中,如下所示:
再一次,此转换的输出并不重要。 变量值的设置很重要。
这是use-dp-var.xq文件的内容:
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace dp = "http://www.datapower.com/extensions";
declare option jsoniq-version "0.4.42";
declare option output:method "json";
let $ssn := .("Social-no")
let $myvar := dp:variable("var://context/mine/myvar2")
return
jn:object(
for $key in jn:keys(.)
let $val := if ($key = "Social-no") then $myvar else .($key)
return { $key : $val }
)
该脚本输出原始消息,用加密的字段值代替原始值。
如果您通过此规则提交样本文档进行加密,则响应类似于以下内容:
{
"State":"MA",
"AccountID":"8458jf8757275234",
"Social-no":"RynTyS5R0hTDDT7e/3OfK0ItyC4rCxZQr8a3D2yITck=",
"Name":"Cartoon Studios"
}
请按照以下步骤使用共享密钥来解密JSON有效负载的元素:
dssn
,如图19所示。 */dssn
。 这是set-dp-var.xq文件的内容:
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace dp = "http://www.datapower.com/extensions";
declare option jsoniq-version "0.4.42";
declare option output:method "json";
let $ssn := .("Social-no")
let $dono := dp:set-variable("var://context/mine/myvar1", $ssn)
let $myvar := dp:variable("var://context/mine/myvar1")
return
jn:object(
for $key in jn:keys(.)
let $val := if ($key = "Social-no") then $myvar else .($key)
return { $key : $val }
)
该脚本从提交的消息中提取Social-no JSON元素的值,将其放在DataPower变量中,然后使用相同的变量再次输出消息。 此转换的输出并不重要; 最重要的是DataPower变量的设置。 在处理策略的下一步中使用此变量。
NULL
。 此样式表检索上一步中设置的DataPower变量的值,使用共享的secred密钥对其解密,然后将结果放入DataPower变量中,如下所示:
再一次,此转换的输出并不重要。 变量值的设置很重要。
这是use-dp-var.xq文件的内容:
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace dp = "http://www.datapower.com/extensions";
declare option jsoniq-version "0.4.42";
declare option output:method "json";
let $ssn := .("Social-no")
let $myvar := dp:variable("var://context/mine/myvar2")
return
jn:object(
for $key in jn:keys(.)
let $val := if ($key = "Social-no") then $myvar else .($key)
return { $key : $val }
)
该脚本输出原始消息,用未加密的字段值代替加密的值(图24)。
如果您提交使用共享密钥加密的有效负载,则将返回原始JSON文档。
{
"Name":"Cartoon Studios",
"AccountID":"8458jf8757275234",
"Social-no":"123-45-6789",
"State":"MA"
}
此方法需要使用加密密钥和证书。 如果尚未创建密钥对象,请按照“ 密钥和证书对”部分中的说明进行操作。
SecureJSON_rule_asencrypt
。 ssna
。 */ssna
。 这是extract-ssn-output.xq文件的内容:
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace dp = "http://www.datapower.com/extensions";
declare option jsoniq-version "0.4.42";
declare option output:method "xml";
let $ssn := .("Social-no")
return
该脚本从JSON请求中提取Social-no元素的值,并将其包装为XML。 在这种情况下,脚本的输出很重要。 此XML输出在下一步操作中被加密。
为了在JSON消息中通过网络传输加密的值,必须对加密的数据块进行URL编码。 下一个动作将执行此任务。
该样式表在PIPE上下文中检索Encrypted Data XML,对其进行URL编码以进行传输,然后将结果放入DataPower变量中。 输出并不重要。
这是use-encrypted-var.xq文件的内容:
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace dp = "http://www.datapower.com/extensions";
declare option jsoniq-version "0.4.42";
declare option output:method "json";
let $ssn := .("Social-no")
let $myvar := dp:variable("var://context/mine/encrypted")
return
jn:object(
for $key in jn:keys(.)
let $val := if ($key = "Social-no") then $myvar else .($key)
return { $key : $val }
)
该脚本输出原始消息,用加密的数据替换Social-no元素。
如果使用此规则将示例JSON文档提交到网关,则将返回部分加密的文档,如下所示:
{
"State":"MA",
"AccountID":"8458jf8757275234",
"Social-no":"%3C%3Fxml+version%3D%221.0%22+encoding%3D%22UTF-8%22%3F%3E%0A%3Cxenc
%3AEncryptedData+Type%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmlenc%23Element%22+xmlns%3Axenc
%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmlenc%23%22%3E%3Cxenc%3AEncryptionMethod+Algorithm
%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2F04%2Fxmlenc%23tripledes-cbc%22%2F%3E%3Cdsig%3AKeyInfo+xmlns
%3Adsig%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23%22%3E%3Cxenc%3AEncryptedKey+Recipient
%3D%22name%3AJason%22%3E%3Cxenc%3AEncryptionMethod+Algorithm%3D%22http%3A%2F%2Fwww.w3.org%2F2001
%2F04%2Fxmlenc%23rsa-1_5%22%2F%3E%3Cdsig%3AKeyInfo%3E%3Cdsig%3AKeyName%3EJason%3C%2Fdsig%3AKeyName
%3E%3C%2Fdsig%3AKeyInfo%3E%3Cxenc%3ACipherData%3E%3Cxenc%3ACipherValue%3EYCbZxpgATnTDySkvoJPJEP
%2BQfqo323mNnozEUxarFohagST06iY4R%2FuwFPsnQEAIVQbmQqxnvUJ3qA63DtBg4GXAEvAPdgyl1947qU8qtDJzTzLixEM7BE7H
%2B7ITTDbPiUm6ZslhYe4hvhWYa441AqaA8tdMCL2e5MhcWliTK4Y%3D%3C%2Fxenc%3ACipherValue%3E%3C%2Fxenc
%3ACipherData%3E%3C%2Fxenc%3AEncryptedKey%3E%3C%2Fdsig%3AKeyInfo%3E%3Cxenc%3ACipherData%3E%3Cxenc
%3ACipherValue%3EhN7LmbrYWJuEM3hFQYjvXua2p%2FtjnQsgto6vQ%2F1HgzEd5SmjLlH5PgL%2FYCop1MSJPiWI9bO
%2BYpl811Hi63gO9M3uf7H73%2F8CLTbKjQWkPvuTX0CkGP7LtHMgPGxLvHZxJpusGBN5f6A%3D%3C%2Fxenc%3ACipherValue
%3E%3C%2Fxenc%3ACipherData%3E%3C%2Fxenc%3AEncryptedData%3E",
"Name":"Cartoon Studios"
}
assn
。 */assn
。 这是set-dpvar-encrypted.xq文件的内容:
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace dp = "http://www.datapower.com/extensions";
declare option jsoniq-version "0.4.42";
declare option output:method "xml";
let $ssn := .("Social-no")
let $dono := dp:set-variable("var://context/mine/encrypted", $ssn)
return
在这种情况下,输出并不重要; 设置变量很重要。 下一个动作将使用它。
posted
的类型。 此样式表的输出很重要。 I由其后的Decrypt操作使用。
这是样式表:
outdata
。 解密后的数据现在位于outdata上下文中。 下一步操作将使用此输入,并将数据放在DataPower变量中,以备后用。
relegate
。 此样式表的输出并不重要; 设置变量很重要。
这是样式表:
这是use-decoded-var.xq文件的内容:
let $ssn := .("Social-no")
let $myvar := dp:variable("var://context/mine/decoded") cast as xs:string
return
jn:object(
for $key in jn:keys(.)
let $val := if ($key = "Social-no") then $myvar else .($key)
return { $key : $val }
)
该文件输出未加密的消息。 如果将使用非对称密钥加密的有效负载提交给网关,则会返回原始消息。
{
"Name":"Cartoon Studios",
"AccountID":"8458jf8757275234",
"Social-no":"123-45-6789",
"State":"MA"
}
本文构建的处理策略为您提供了三种不同的方法来保护在基于REST的体系结构中传输的JSON有效负载。 无论传输协议如何,这都会保留有效负载的私密性。 您学习了如何加密整个有效负载或仅选择元素。 对于给定的用例,您可能只需要使用一种方法。 但是,这为您提供了仅创建方案所需的安全处理的策略或基础。
图40显示了处理策略以及本文中描述的所有规则。
翻译自: https://www.ibm.com/developerworks/websphere/library/techarticles/1401_shute/1401_shute.html