基于Hash摘要签名的公网URL签名验证设计方案

基于Hash摘要签名的公网URL签名验证设计与约定

为什么要对url参数签名

在特定的环境下存在A系统页面打开B系统(不是同一个公司)的需求,由于B系统中不存在用户登陆,所以必须保证A通过URL调用带给B的参数是可信且未经篡改的。比如A的用户需要打开B的页面查看待审批充值订单url https://admin.isexample.com/admin/abc?isid=10000011 由于这个url是在用户浏览器上可以修改的,为了避免用户在浏览器上将isid改为其他值(比如https://admin.isexample.com/admin/abc?isid=10000012 ),这会导致系统的用户信息泄露,为了避免这种情况产生,我们需要对url中的参数进行签名。

有哪些关注点

  1. url参数放篡改
  2. url参数仿复用、仿重放攻击(url有有效期,生成时间与访问时间间隔太久会阻止访问)
  3. 验证通过后需要重定向一次 防止用户刷新原来的页面导致一次性token再次使用而系统返回错误,还需要一个随机字符串来防止每次的提交可能相同,即除了时间戳还需要一个随机字符串nonce_str
  4. 需要统一时区(比如以0时区为标准)
  5. 私下约定的加密字符串更换成本(使用两个?)
  6. Get请求url太长是否影响、大小写是否影响
  7. 通用性,需要考虑出来当前网页url验证外,还可能在系统其他部分使用(可能被作>统一拦截)
  8. 签名认证的结果是否只对当前页面有效,其他页面是否可以跳过认证(不安全,认证应该是一次性的,每次不同系统的交互都应该重新认证鉴权,如何保证重定向时认证息的传递,页面刷新呢?)
  9. 加密时,需要先做签名再做urlencode,解密时需要先urldecode,再签名对比
  10. url传递的参数值不支持数组形式 比如 a=1&a=2&a=3 是不被支持的
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,这是一个涉及到加密算法的问题,需要使用OpenSSL库来实现。以下是一个简单的示例程序,可以用来进行签名验证签名: ```c++ #include <iostream> #include <openssl/rsa.h> #include <openssl/pem.h> #include <openssl/err.h> using namespace std; // 生成密钥对 bool generate_key(int bits, string pub_file, string pri_file) { RSA *rsa = RSA_new(); BIGNUM *bn = BN_new(); BN_set_word(bn, RSA_F4); RSA_generate_key_ex(rsa, bits, bn, NULL); // 保存公钥 FILE *pub_fp = fopen(pub_file.c_str(), "wb"); PEM_write_RSAPublicKey(pub_fp, rsa); fclose(pub_fp); // 保存私钥 FILE *pri_fp = fopen(pri_file.c_str(), "wb"); PEM_write_RSAPrivateKey(pri_fp, rsa, NULL, NULL, 0, NULL, NULL); fclose(pri_fp); RSA_free(rsa); BN_free(bn); return true; } // 签名 bool sign(string pri_file, string data, string &signature) { RSA *rsa = RSA_new(); // 读取私钥 FILE *fp = fopen(pri_file.c_str(), "rb"); rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); fclose(fp); // 计算签名 unsigned char hash[SHA256_DIGEST_LENGTH]; SHA256_CTX sha256; SHA256_Init(&sha256); SHA256_Update(&sha256, data.c_str(), data.size()); SHA256_Final(hash, &sha256); unsigned char sign[RSA_size(rsa)]; unsigned int sign_len; int ret = RSA_sign(NID_sha256, hash, SHA256_DIGEST_LENGTH, sign, &sign_len, rsa); if (ret != 1) { RSA_free(rsa); return false; } signature = string((char *)sign, sign_len); RSA_free(rsa); return true; } // 验证签名 bool verify(string pub_file, string data, string signature) { RSA *rsa = RSA_new(); // 读取公钥 FILE *fp = fopen(pub_file.c_str(), "rb"); rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL); fclose(fp); // 计算消息摘要 unsigned char hash[SHA256_DIGEST_LENGTH]; SHA256_CTX sha256; SHA256_Init(&sha256); SHA256_Update(&sha256, data.c_str(), data.size()); SHA256_Final(hash, &sha256); // 验证签名 int ret = RSA_verify(NID_sha256, hash, SHA256_DIGEST_LENGTH, (unsigned char *)signature.c_str(), signature.size(), rsa); RSA_free(rsa); return ret == 1; } int main() { // 生成密钥对 generate_key(2048, "public.pem", "private.pem"); // 签名验证签名 string data = "hello, world!"; string signature; if (sign("private.pem", data, signature)) { cout << "signature: " << signature << endl; if (verify("public.pem", data, signature)) { cout << "verify success" << endl; } else { cout << "verify fail" << endl; } } else { cout << "sign fail" << endl; } return 0; } ``` 这个程序生成了一个2048位的RSA密钥对,并使用SHA256算法进行签名验证签名。你可以根据自己的需要修改程序,比如可以使用其他加密算法、调整密钥长度等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值