接口测试 在 postman 中使用 rsa 加密

雨夜狂奔 · 2018年06月29日 · 最后由 雨夜狂奔 回复于 2021年09月08日 · 8548 次阅读

为什么需要

有一些接口测试需要进行加密,直接用 postman 就有一点满足不了需求了,幸好 postman 提供了扩展功能,可以通过pre-script进行加密,然后再进行数据请求

社区已经有哪些文章

postman 进行加密已经详细说明了如何使用 postman 进行加密。
但是有一个问题,postman 本身并不支持 RSA 的加解密,所以应该怎么做呢?

postman 进行 RSA 加解密的解决办法

方案介绍

postman 提供了变量功能,可以将支持 RSA 加解密的代码放到变量中,然后通过eval加载到当前环境中来,就可以使用自定义的加解密方案了。
下面介绍了生成forge.js文件的具体方式,如果想要直接使用可以前往我的 github 页面进行下载

安装 node 和 git

安装 node 主要是进行打包,必须安装。
安装 git 主要是进行代码下载,可选,可以手动进行下载代码。

下载 forge 源码

git clone https://github.com/digitalbazaar/forge.git
cd /path/to/your/dir
npm install

修改配置

webpack.config.js中的umd替换为var,现在配置文件长这样

const bundle = Object.assign({}, common, {
    output: {
      path: path.join(__dirname, 'dist'),
      filename: info.filenameBase + '.js',
      library: info.library || '[name]',
      libraryTarget: info.libraryTarget || 'var'
    }
  });
  if(info.library === null) {
    delete bundle.output.library;
  }
  if(info.libraryTarget === null) {
    delete bundle.output.libraryTarget;
  }

  // optimized and minified bundle
  const minify = Object.assign({}, common, {
    output: {
      path: path.join(__dirname, 'dist'),
      filename: info.filenameBase + '.min.js',
      library: info.library || '[name]',
      libraryTarget: info.libraryTarget || 'var'
    },
    devtool: 'cheap-module-source-map',
    plugins: [
      new webpack.optimize.UglifyJsPlugin({
        sourceMap: true,
        compress: {
          warnings: true
        },
        output: {
          comments: false
        }
        //beautify: true
      })
    ]
  });

重新打包

npm run build

完成之后在dist目录下就有一个文件forge.js,这就是我们想要的(在我的项目页面有现成的下载)

文件如何生成介绍完毕,下面介绍如何使用这个文件

使用生成的forge.js进行 RSA 加解密

下面介绍两种办法

手动进行添加变量

postman 提供了变量功能,所以可以在 postman 中手动添加一个变量forgeJS,值设置为forge.js文件中的所有内容,全选并复制粘贴进去

然后新建一个请求,在pre-script中添加下面的代码

eval(postman.getGlobalVariable("forgeJS"));

const public_key = '-----BEGIN PUBLIC KEY-----\n'+
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDORoOSW2gbHl6s/YmS1jWxb954\n'+
'X/jflZ2dK65oM/Bxii2Iba80IiC9+Sa1phmOVDAk+IVDsPNZ+YJ2Qg0hPmoLSLxe\n'+
'f2A6ySJPl5su8TaGOuVZg1SRyk55bjHymQUnxryD/ml1EmBUaGcrs9FCiVBy38kg\n'+
'eZNbCexucVQxn6OYlwIDAQAB\n'+
'-----END PUBLIC KEY-----'

const private_key = '-----BEGIN PRIVATE KEY-----\n' +
'MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAM5Gg5JbaBseXqz9\n' +
'iZLWNbFv3nhf+N+VnZ0rrmgz8HGKLYhtrzQiIL35JrWmGY5UMCT4hUOw81n5gnZC\n' +
'DSE+agtIvF5/YDrJIk+Xmy7xNoY65VmDVJHKTnluMfKZBSfGvIP+aXUSYFRoZyuz\n' +
'0UKJUHLfySB5k1sJ7G5xVDGfo5iXAgMBAAECgYEAk6KQZN4bQt2XsYS9RGUghOCm\n' +
'f81g2NXCu00aROZ3vyvArxaiAVQzzwRWGkjJnb7PvoZJC0vIwKr+HxnjP9nmFufd\n' +
'+0EnBT+imYSzrfZhfGGwyI6EIyy/XcoW5lf0xltx3w9mJicnR9kMzNtZ5mNGPMNn\n' +
'CgAgjvZqnWYb+f6tb/ECQQD0tdpg8ts3puXclPe51my+LbKhEbyFSMzvtMTDCRmO\n' +
'd0jrmZhQomsZacC8+l+2l6WTj5vrhVQlAVUeUJ7kldQNAkEA18q53wor6a4Cv0OL\n' +
'xFzBWXRCMVFfyCWAFQUpTSGrIM/X4Lx30IZCShtvkdh1ky39b9T6lpOjES7MK4Dh\n' +
'xttCMwJAUGBi6DEcm/zvxzIO5DVv5k9wOsNunoC4/4rqjf0xLcA0bV43z1RpxSEd\n' +
'M3UxdvH8aqli10slxjnX0Ws9pWspCQJBALqSncgYzETbXaauqO5a4BUOrphjafPr\n' +
'cGU8NCxrGsFg0p6NdO5G1pOqSvmHdIiPL9t8AjkkZs3Zb0+BvDOpqP8CQQDZhfh4\n' +
'/c/Qzp4szj7+GXTZ1cmGwAuFo2/9uiumUAS3f19EpgoV9u9eyJ4gZPEBDvAjO961\n' +
'kAjdja4DAy4SbCXy\n' +
'-----END PRIVATE KEY-----'

//encrypt text "plaintext"
var publicKey = forge.pki.publicKeyFromPem(public_key);
var encryptedText = forge.util.encode64(publicKey.encrypt("plaintext", 'RSA-OAEP', {
  md: forge.md.sha1.create(),
  mgf1: {
    md: forge.md.sha1.create()
  }
}));
console.log("encrypted text:" + encryptedText);

// decrypt text
var privateKey = forge.pki.privateKeyFromPem(private_key);
var decryptedText = privateKey.decrypt(forge.util.decode64(encryptedText), 'RSA-OAEP', {
  md: forge.md.sha1.create(),
  mgf1: {
    md: forge.md.sha1.create()
  }
});

console.log("dectypted text:" + decryptedText);


发送请求就可以看到执行结果,这个例子是把plaintext先进行加密,然后进行解密打印出来,结果可以在 postman 的 console 窗口查看

将文件传到 web 服务器进行自动设置

上面的办法有点太麻烦了,而且由于文件太大,添加变量的时候会很卡很卡,所以可以将forge.js添加到 web 服务器(本地的也可以,但是直接用 github 的链接不行),然后跟上面步骤一样的,但是pre-script使用下面的代码,注意要把http://path/to/forge.js换成你自己的服务器的地址。

//download forgeJS from web and set varible

if (!pm.globals.has("forgeJS")) {
    pm.sendRequest("https://raw.githubusercontent.com/loveiset/RSAForPostman/master/forge.js", function (err, res) {
        if (err) {
            console.log(err);
        } else {
            pm.globals.set("forgeJS", res.text());
        }
    })
} else {
    eval(pm.globals.get("forgeJS"))
    const public_key = '-----BEGIN PUBLIC KEY-----\n' +
        'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDORoOSW2gbHl6s/YmS1jWxb954\n' +
        'X/jflZ2dK65oM/Bxii2Iba80IiC9+Sa1phmOVDAk+IVDsPNZ+YJ2Qg0hPmoLSLxe\n' +
        'f2A6ySJPl5su8TaGOuVZg1SRyk55bjHymQUnxryD/ml1EmBUaGcrs9FCiVBy38kg\n' +
        'eZNbCexucVQxn6OYlwIDAQAB\n' +
        '-----END PUBLIC KEY-----'

    const private_key = '-----BEGIN PRIVATE KEY-----\n' +
        'MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAM5Gg5JbaBseXqz9\n' +
        'iZLWNbFv3nhf+N+VnZ0rrmgz8HGKLYhtrzQiIL35JrWmGY5UMCT4hUOw81n5gnZC\n' +
        'DSE+agtIvF5/YDrJIk+Xmy7xNoY65VmDVJHKTnluMfKZBSfGvIP+aXUSYFRoZyuz\n' +
        '0UKJUHLfySB5k1sJ7G5xVDGfo5iXAgMBAAECgYEAk6KQZN4bQt2XsYS9RGUghOCm\n' +
        'f81g2NXCu00aROZ3vyvArxaiAVQzzwRWGkjJnb7PvoZJC0vIwKr+HxnjP9nmFufd\n' +
        '+0EnBT+imYSzrfZhfGGwyI6EIyy/XcoW5lf0xltx3w9mJicnR9kMzNtZ5mNGPMNn\n' +
        'CgAgjvZqnWYb+f6tb/ECQQD0tdpg8ts3puXclPe51my+LbKhEbyFSMzvtMTDCRmO\n' +
        'd0jrmZhQomsZacC8+l+2l6WTj5vrhVQlAVUeUJ7kldQNAkEA18q53wor6a4Cv0OL\n' +
        'xFzBWXRCMVFfyCWAFQUpTSGrIM/X4Lx30IZCShtvkdh1ky39b9T6lpOjES7MK4Dh\n' +
        'xttCMwJAUGBi6DEcm/zvxzIO5DVv5k9wOsNunoC4/4rqjf0xLcA0bV43z1RpxSEd\n' +
        'M3UxdvH8aqli10slxjnX0Ws9pWspCQJBALqSncgYzETbXaauqO5a4BUOrphjafPr\n' +
        'cGU8NCxrGsFg0p6NdO5G1pOqSvmHdIiPL9t8AjkkZs3Zb0+BvDOpqP8CQQDZhfh4\n' +
        '/c/Qzp4szj7+GXTZ1cmGwAuFo2/9uiumUAS3f19EpgoV9u9eyJ4gZPEBDvAjO961\n' +
        'kAjdja4DAy4SbCXy\n' +
        '-----END PRIVATE KEY-----'


    //encrypt text "plaintext"
    var publicKey = forge.pki.publicKeyFromPem(public_key);
    var encryptedText = forge.util.encode64(publicKey.encrypt("plaintext", 'RSA-OAEP', {
        md: forge.md.sha1.create(),
        mgf1: {
            md: forge.md.sha1.create()
        }
    }));
    console.log("encrypted text:" + encryptedText);

    // decrypt text
    var privateKey = forge.pki.privateKeyFromPem(private_key);
    var decryptedText = privateKey.decrypt(forge.util.decode64(encryptedText), 'RSA-OAEP', {
        md: forge.md.sha1.create(),
        mgf1: {
            md: forge.md.sha1.create()
        }
    });

    console.log("dectypted text:" + decryptedText);


}

好了,到这里,已经可以使用 postman 进行 RSA 的加解密了!!

其它事项说明

引用

forge 是其它开源项目,这里进行了直接的使用
项目地址:https://github.com/digitalbazaar/forge
而且关于 RSA 加密的相关文档同样的可以查看这个地址

如何删除forgeJS变量

相信实验过的人已经发现了,由于文件内容太大,编辑的时候会导致 postman 特别卡,所以我反悔了,想要删除掉这个变量怎么办。
别急,首先新增一个空白请求,url 随便填一个,比如www.baidu.com,然后在pre-script中添加下面的内容

pm.globals.unset("forgeJS");

发送一下请求,这个变量就删掉了

其它说明

毕竟这个方式比较奇特,还是希望 postman 官方将 RSA 加密尽早加入到支持列表中。

项目地址

关于其他更详细的介绍以及相关的文件,可以在这个地址中查看:https://github.com/loveiset/RSAForPostman

共收到 10 条回复 时间 点赞

forge.js ,pre-script 楼主这 2 个手动添加的代码能复制一下吗?我按照你上面的步骤报错,谢谢

youxiaoxian 回复

直接复制 github 的 prescript 就行了,url 你填下百度,然后发送一个请求,就可以看到加解密成功了,我刚试了没问题

//download forgeJS from web and set varible
if(!pm.globals.has("forgeJS")){
        pm.sendRequest("https://raw.githubusercontent.com/loveiset/RSAForPostman/master/forge.js", function (err, res) {
        if (err) {
            console.log(err);}
        else {
            pm.globals.set("forgeJS", res.text());}
})}

eval(postman.getGlobalVariable("forgeJS"));

const public_key = '-----BEGIN PUBLIC KEY-----\n'+
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDORoOSW2gbHl6s/YmS1jWxb954\n'+
'X/jflZ2dK65oM/Bxii2Iba80IiC9+Sa1phmOVDAk+IVDsPNZ+YJ2Qg0hPmoLSLxe\n'+
'f2A6ySJPl5su8TaGOuVZg1SRyk55bjHymQUnxryD/ml1EmBUaGcrs9FCiVBy38kg\n'+
'eZNbCexucVQxn6OYlwIDAQAB\n'+
'-----END PUBLIC KEY-----'

const private_key = '-----BEGIN PRIVATE KEY-----\n' +
'MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAM5Gg5JbaBseXqz9\n' +
'iZLWNbFv3nhf+N+VnZ0rrmgz8HGKLYhtrzQiIL35JrWmGY5UMCT4hUOw81n5gnZC\n' +
'DSE+agtIvF5/YDrJIk+Xmy7xNoY65VmDVJHKTnluMfKZBSfGvIP+aXUSYFRoZyuz\n' +
'0UKJUHLfySB5k1sJ7G5xVDGfo5iXAgMBAAECgYEAk6KQZN4bQt2XsYS9RGUghOCm\n' +
'f81g2NXCu00aROZ3vyvArxaiAVQzzwRWGkjJnb7PvoZJC0vIwKr+HxnjP9nmFufd\n' +
'+0EnBT+imYSzrfZhfGGwyI6EIyy/XcoW5lf0xltx3w9mJicnR9kMzNtZ5mNGPMNn\n' +
'CgAgjvZqnWYb+f6tb/ECQQD0tdpg8ts3puXclPe51my+LbKhEbyFSMzvtMTDCRmO\n' +
'd0jrmZhQomsZacC8+l+2l6WTj5vrhVQlAVUeUJ7kldQNAkEA18q53wor6a4Cv0OL\n' +
'xFzBWXRCMVFfyCWAFQUpTSGrIM/X4Lx30IZCShtvkdh1ky39b9T6lpOjES7MK4Dh\n' +
'xttCMwJAUGBi6DEcm/zvxzIO5DVv5k9wOsNunoC4/4rqjf0xLcA0bV43z1RpxSEd\n' +
'M3UxdvH8aqli10slxjnX0Ws9pWspCQJBALqSncgYzETbXaauqO5a4BUOrphjafPr\n' +
'cGU8NCxrGsFg0p6NdO5G1pOqSvmHdIiPL9t8AjkkZs3Zb0+BvDOpqP8CQQDZhfh4\n' +
'/c/Qzp4szj7+GXTZ1cmGwAuFo2/9uiumUAS3f19EpgoV9u9eyJ4gZPEBDvAjO961\n' +
'kAjdja4DAy4SbCXy\n' +
'-----END PRIVATE KEY-----'

//encrypt text "plaintext"
var publicKey = forge.pki.publicKeyFromPem(public_key);
var encryptedText = forge.util.encode64(publicKey.encrypt("plaintext", 'RSA-OAEP', {
  md: forge.md.sha1.create(),
  mgf1: {
    md: forge.md.sha1.create()
  }
}));
console.log("encrypted text:" + encryptedText);

// decrypt text
var privateKey = forge.pki.privateKeyFromPem(private_key);
var decryptedText = privateKey.decrypt(forge.util.decode64(encryptedText), 'RSA-OAEP', {
  md: forge.md.sha1.create(),
  mgf1: {
    md: forge.md.sha1.create()
  }
});

console.log("dectypted text:" + decryptedText);

能不能介绍的更详细点

lujieli 回复

复制 2 楼的脚本,发送一个请求就行了,就可以看到加密和解密过程了,加密和解密的代码也在 2 楼的脚本里面,具体是哪有疑问呢

不是很懂这个 eval(postman.getGlobalVariable("forgeJS")),因为 get 之后,调用 forge ,但是提示 forge is not defined

dengying 回复

相当于是从网上下载了一个 js,然后 eval 注入到环境里面,所以如果要成功,要能够下载这个 js 文件,下载之后会自动把 js 的值设置到 postman 的变量里面去

if(!pm.globals.has("forgeJS")){
        pm.sendRequest("https://raw.githubusercontent.com/loveiset/RSAForPostman/master/forge.js", function (err, res) {
        if (err) {
            console.log(err);}
        else {
            pm.globals.set("forgeJS", res.text());}
})}

如果你没成功,可以打开 postman 的 console 看看是不是下载这个文件失败了(由于使用的是 github 链接,可能连不上)。

如果实在不行,建议手动下载这个 js,然后自建一个 http 服务器,把这个文件放上去,链接改为自己的。(如果是 windows 可以使用 hfs,一个很小的文件,运行就可以了)

雨夜狂奔 回复

我有使用 hfs ,forge.js 从我本地成功下载了,log 看到也下载成功

为了验证,也直接复制了你提供的代码,改了 url 地址为我本地 http://127.0.0.1/forge.js,这个 forge.js 也更换为了你项目中的 forge.js,但是调用的时候还是会提示 forge is not defined;

而且打日志看 forgeJS 是否有真的设置下去,又会很卡,大概是设置下去了吧,所以不知道什么原因

dengying 回复

找到问题了,是新版 postman 不一定按照语句的顺序来执行,导致forgeJS变量还没有设置的时候就去使用导致报错,修改了一下脚本,这个应该没问题了,复制进去之后先执行一次,第二次在 console 就能看到加解密结果了

//download forgeJS from web and set varible

if (!pm.globals.has("forgeJS")) {
    pm.sendRequest("http://10.52.16.143/logs/forge.js", function (err, res) {
        if (err) {
            console.log(err);
        } else {
            pm.globals.set("forgeJS", res.text());
        }
    })
} else {
    eval(pm.globals.get("forgeJS"))
    const public_key = '-----BEGIN PUBLIC KEY-----\n' +
        'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDORoOSW2gbHl6s/YmS1jWxb954\n' +
        'X/jflZ2dK65oM/Bxii2Iba80IiC9+Sa1phmOVDAk+IVDsPNZ+YJ2Qg0hPmoLSLxe\n' +
        'f2A6ySJPl5su8TaGOuVZg1SRyk55bjHymQUnxryD/ml1EmBUaGcrs9FCiVBy38kg\n' +
        'eZNbCexucVQxn6OYlwIDAQAB\n' +
        '-----END PUBLIC KEY-----'

    const private_key = '-----BEGIN PRIVATE KEY-----\n' +
        'MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAM5Gg5JbaBseXqz9\n' +
        'iZLWNbFv3nhf+N+VnZ0rrmgz8HGKLYhtrzQiIL35JrWmGY5UMCT4hUOw81n5gnZC\n' +
        'DSE+agtIvF5/YDrJIk+Xmy7xNoY65VmDVJHKTnluMfKZBSfGvIP+aXUSYFRoZyuz\n' +
        '0UKJUHLfySB5k1sJ7G5xVDGfo5iXAgMBAAECgYEAk6KQZN4bQt2XsYS9RGUghOCm\n' +
        'f81g2NXCu00aROZ3vyvArxaiAVQzzwRWGkjJnb7PvoZJC0vIwKr+HxnjP9nmFufd\n' +
        '+0EnBT+imYSzrfZhfGGwyI6EIyy/XcoW5lf0xltx3w9mJicnR9kMzNtZ5mNGPMNn\n' +
        'CgAgjvZqnWYb+f6tb/ECQQD0tdpg8ts3puXclPe51my+LbKhEbyFSMzvtMTDCRmO\n' +
        'd0jrmZhQomsZacC8+l+2l6WTj5vrhVQlAVUeUJ7kldQNAkEA18q53wor6a4Cv0OL\n' +
        'xFzBWXRCMVFfyCWAFQUpTSGrIM/X4Lx30IZCShtvkdh1ky39b9T6lpOjES7MK4Dh\n' +
        'xttCMwJAUGBi6DEcm/zvxzIO5DVv5k9wOsNunoC4/4rqjf0xLcA0bV43z1RpxSEd\n' +
        'M3UxdvH8aqli10slxjnX0Ws9pWspCQJBALqSncgYzETbXaauqO5a4BUOrphjafPr\n' +
        'cGU8NCxrGsFg0p6NdO5G1pOqSvmHdIiPL9t8AjkkZs3Zb0+BvDOpqP8CQQDZhfh4\n' +
        '/c/Qzp4szj7+GXTZ1cmGwAuFo2/9uiumUAS3f19EpgoV9u9eyJ4gZPEBDvAjO961\n' +
        'kAjdja4DAy4SbCXy\n' +
        '-----END PRIVATE KEY-----'


    //encrypt text "plaintext"
    var publicKey = forge.pki.publicKeyFromPem(public_key);
    var encryptedText = forge.util.encode64(publicKey.encrypt("plaintext", 'RSA-OAEP', {
        md: forge.md.sha1.create(),
        mgf1: {
            md: forge.md.sha1.create()
        }
    }));
    console.log("encrypted text:" + encryptedText);

    // decrypt text
    var privateKey = forge.pki.privateKeyFromPem(private_key);
    var decryptedText = privateKey.decrypt(forge.util.decode64(encryptedText), 'RSA-OAEP', {
        md: forge.md.sha1.create(),
        mgf1: {
            md: forge.md.sha1.create()
        }
    });

    console.log("dectypted text:" + decryptedText);


}

楼主知道 plaintext 太长,报 “Error: RSAES-OAEP input message length is too long.” 如何解决吗?😂 😂 😂

音音怪 回复

RSA 本来就加密不了长度太长的内容,可以加密的长度上限有个计算公式,可以看一下,另外 padding 方式也会影响加密长度,可以参考下别人的回答
https://github.com/digitalbazaar/forge/issues/398

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册