帮助帮助
  • 首页
  • 帮助文档
  • 后端python
  • 开放平台
返回控制台
  • 首页
  • 功能插件
  • 密钥管理
  • 单点登录
    • 开发指南
    • SAML2.0配置
    • 自定义接口配置
  • Webhook
    • webhook开发指南
    • 表单webhook
    • 通讯录webhook
    • 系统webhook
    • 加密方式及解密算法
  • API
    • 开发指南
    • 数据筛选器
    • 错误对照表
    • 字段与数据类型对照表
    • POST接口
    • 应用体系-表单管理
      • 查询表单字段结构
      • 获取表单基本信息
      • 查询表单计划任务列表
      • 执行计划任务
      • 开启停用计划任务
      • 查询成员控件配置信息
      • 查询部门控件配置信息
      • 修改成员控件
      • 修改部门控件
      • 查询流程节点配置信息
      • 修改流程节点配置
    • 应用体系-表单数据
      • 新增数据
      • 查询单条数据
      • 查询多条数据
      • 编辑数据
      • 删除数据
      • 批量新增数据
      • 查询数据总数
      • 批量修改数据
      • 批量删除数据
      • 新增唯一数据
      • 新增多条唯一数据
    • 应用体系-表单流程
      • 发起流程
      • 结束流程
      • 流程修改
      • 流程催办
      • 批量结束流程
      • 获取流程操作日志
      • 查询流程信息
      • 查询流程待办信息
      • 查询流程待办数量
    • 应用体系-数据视图
      • 查询数据视图输出表字段
      • 查询数据视图数据
      • 查询数据视图数据总数
      • 数据视图修改
    • 应用体系-聚合表
      • 查询聚合表输出字段
      • 查询聚合表数据
      • 查询聚合表数据总数
      • 聚合表修改
    • 通讯录体系-成员
      • 获取成员详细信息
      • 修改成员信息
      • 员工离职
      • 员工离职恢复
      • 删除成员
      • 指定部门下添加一位成员
      • 查询成员列表
      • 成员转外部联系人
      • 修改成员职位
    • 通讯录体系-部门
      • 创建部门
      • 修改部门名称
      • 修改父级部门
      • 查询指定部门下的所有子部门信息
      • 查询部门信息
      • 删除部门
      • 获取部门成员
    • 通讯录体系-职位
      • 获取职位列表
      • 添加职位
      • 修改职位
      • 删除职位
    • 通讯录体系-角色
      • 新建角色组
      • 修改角色组
      • 获取角色组信息
      • 获取角色组列表
      • 删除角色组
      • 获取角色组成员列表
      • 批量创建角色组
      • 批量删除角色组
      • 角色组添加成员
      • 删除角色组成员
    • 通讯录体系-外部联系人分组
      • 获取外部联系人分组列表
      • 获取外部联系人分组成员列表
      • 获取外部联系人分组信息
      • 新建外部联系人分组
      • 修改外部联系人分组名称
      • 删除外部联系人分组
      • 批量删除外部联系人分组
      • 批量新增外部联系人分组
    • 通讯录体系-外部联系人管理
      • 获取外部联系人成员信息
      • 修改外部联系人成员信息
      • 外部联系人删除
      • 外部联系人成员删除恢复
      • 外部联系人转成员
    • 通讯录体系-管理组
      • 新建管理组
      • 查询管理组列表
      • 查询管理组详情
      • 删除管理组
      • 修改普通管理组详情
      • 修改系统管理组管理员
    • 通讯录体系-互联组织
      • 列出我连接的企业
      • 列出我连接的企业的对接人
      • 获取我连接的企业对接人的详细信息
      • 查询互联企业角色列表
      • 查询互联企业对接部门列表
      • 查询互联企业对接部门的成员
    • 平台体系-账号
      • 注册账号
      • 加入某个团队
      • 加入某个团队的外部联系人
      • 账号绑定微信
      • 账号解绑微信
      • 查询账号基本信息
      • 修改账号信息
      • 登录账号
      • 查询账号列表
      • 修改团队信息
    • 平台体系-消息
      • 发送邮件消息
      • 发送钉钉消息
      • 发送飞书消息
      • 发送微信消息
      • 发送企业微信消息
    • 平台体系-应用管理
      • 创建应用分组
      • 查询应用分组列表
      • 应用分组重命名
      • 应用分组删除
      • 查询应用列表
      • 获取应用的表单列表
      • 查询应用下的待办数量
      • 获取数据视图列表
      • 查询聚合表列表
      • 打印模板打印数据
      • 查询打印模板列表
      • 自定义数据打印
      • 查询报表控件
      • 查询表单权限组列表
      • 创建表单自定义权限组
      • 修改表单权限组信息
      • 批量修改表单权限组
      • 删除表单自定义权限组
    • 平台体系-密钥管理
      • 创建秘钥
      • 查询密钥
      • 删除秘钥
    • 平台体系-性能配置
      • 查询用户基础配置信息
      • 查询用户汇总配置信息
      • 修改用户基础配置信息
      • 为用户赠送指定配置
      • 查询配置赠送列表
      • 查询配置消耗
      • 查询已购买套餐列表
    • 平台体系-设置
      • 查询模板应用总数
      • 查询模板应用列表
      • 安装模板应用
      • 查询站点公告
      • 修改站点公告
      • 查询微信access_token
    • 平台体系-日志查询
      • 查询登录日志
      • 查询日志类型
      • 查询平台操作日志
      • 查询应用日志
    • 平台体系-webhook管理
      • 查询webhook列表
      • 新建webhook
      • 修改webhook
      • 删除webhook

加密方式及解密算法

  • 加密算法
  • 解密算法
    • PHP
    • Java
    • Golang
    • Python
    • C
    • Node.js

加密算法

EncryptKey即在界面填写的Secret值。

加密过程:

​ 1、使用SHA256对EncryptKey进行哈希得到密钥key;

​ 2、生成16个字节的随机数作为初始向量iv;

​ 3、使用iv和key对事件内容加密得到encryped_event;(事件内容采用AES-256-CBC加密)

​ 4、应用收到的密文encrypt为base64(iv+encryped_event)。

根据加密算法,自行进行解密,可参考解密算法示例。

解密算法

以下提供了PHP、Java、Golang、Python、C#、Node.js等这几种语言的解密算法供开发者参考。

PHP

  1. <?php
  2. function decrypt($key, $input)
  3. {
  4. $key = hash('sha256', $key, true);
  5. $input_bin = base64_decode($input);
  6. $data = substr($input_bin, 16);
  7. $iv = substr($input_bin, 0, 16);
  8. $output = openssl_decrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
  9. return $output;
  10. }
  11. $res = decrypt("test key", "P37w+VZImNgPEO1RBhJ6RtKl7n6zymIbEG1pReEzghk=");
  12. var_dump($res); // string(11) "hello world"
  13. 复制

Java

  1. package com.larksuite.oapi.sample;
  2. import javax.crypto.Cipher;
  3. import javax.crypto.spec.IvParameterSpec;
  4. import javax.crypto.spec.SecretKeySpec;
  5. import java.nio.charset.StandardCharsets;
  6. import java.security.MessageDigest;
  7. import java.security.NoSuchAlgorithmException;
  8. import java.util.Base64;
  9. public class Decrypt {
  10. public static void main(String[] args) throws Exception {
  11. Decrypt d = new Decrypt("test key");
  12. System.out.println(d.decrypt("P37w+VZImNgPEO1RBhJ6RtKl7n6zymIbEG1pReEzghk=")); //hello world
  13. }
  14. private byte[] keyBs;
  15. public Decrypt(String key) {
  16. MessageDigest digest = null;
  17. try {
  18. digest = MessageDigest.getInstance("SHA-256");
  19. } catch (NoSuchAlgorithmException e) {
  20. // won't happen
  21. }
  22. keyBs = digest.digest(key.getBytes(StandardCharsets.UTF_8));
  23. }
  24. public String decrypt(String base64) throws Exception {
  25. byte[] decode = Base64.getDecoder().decode(base64);
  26. Cipher cipher = Cipher.getInstance("AES/CBC/NOPADDING");
  27. byte[] iv = new byte[16];
  28. System.arraycopy(decode, 0, iv, 0, 16);
  29. byte[] data = new byte[decode.length - 16];
  30. System.arraycopy(decode, 16, data, 0, data.length);
  31. cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyBs, "AES"), new IvParameterSpec(iv));
  32. byte[] r = cipher.doFinal(data);
  33. if (r.length > 0) {
  34. int p = r.length - 1;
  35. for (; p >= 0 && r[p] <= 16; p--) {
  36. }
  37. if (p != r.length - 1) {
  38. byte[] rr = new byte[p + 1];
  39. System.arraycopy(r, 0, rr, 0, p + 1);
  40. r = rr;
  41. }
  42. }
  43. return new String(r, StandardCharsets.UTF_8);
  44. }
  45. }复制

Golang

  1. package main
  2. import (
  3. "crypto/aes"
  4. "crypto/cipher"
  5. "crypto/sha256"
  6. "encoding/base64"
  7. "errors"
  8. "fmt"
  9. "strings"
  10. )
  11. func main() {
  12. s, err := Decrypt("P37w+VZImNgPEO1RBhJ6RtKl7n6zymIbEG1pReEzghk=", "test key")
  13. if err != nil {
  14. panic(err)
  15. }
  16. fmt.Println(s) //hello world
  17. }
  18. func Decrypt(encrypt string, key string) (string, error) {
  19. buf, err := base64.StdEncoding.DecodeString(encrypt)
  20. if err != nil {
  21. return "", fmt.Errorf("base64StdEncode Error[%v]", err)
  22. }
  23. if len(buf) < aes.BlockSize {
  24. return "", errors.New("cipher too short")
  25. }
  26. keyBs := sha256.Sum256([]byte(key))
  27. block, err := aes.NewCipher(keyBs[:sha256.Size])
  28. if err != nil {
  29. return "", fmt.Errorf("AESNewCipher Error[%v]", err)
  30. }
  31. iv := buf[:aes.BlockSize]
  32. buf = buf[aes.BlockSize:]
  33. // CBC mode always works in whole blocks.
  34. if len(buf)%aes.BlockSize != 0 {
  35. return "", errors.New("ciphertext is not a multiple of the block size")
  36. }
  37. mode := cipher.NewCBCDecrypter(block, iv)
  38. mode.CryptBlocks(buf, buf)
  39. n := strings.Index(string(buf), "{")
  40. if n == -1 {
  41. n = 0
  42. }
  43. m := strings.LastIndex(string(buf), "}")
  44. if m == -1 {
  45. m = len(buf) - 1
  46. }
  47. return string(buf[n : m+1]), nil
  48. }复制

Python

  1. import hashlib
  2. import base64
  3. from Crypto.Cipher import AES
  4. class AESCipher(object):
  5. def __init__(self, key):
  6. self.bs = AES.block_size
  7. self.key=hashlib.sha256(AESCipher.str_to_bytes(key)).digest()
  8. @staticmethod
  9. def str_to_bytes(data):
  10. u_type = type(b"".decode('utf8'))
  11. if isinstance(data, u_type):
  12. return data.encode('utf8')
  13. return data
  14. @staticmethod
  15. def _unpad(s):
  16. return s[:-ord(s[len(s) - 1:])]
  17. def decrypt(self, enc):
  18. iv = enc[:AES.block_size]
  19. cipher = AES.new(self.key, AES.MODE_CBC, iv)
  20. return self._unpad(cipher.decrypt(enc[AES.block_size:]))
  21. def decrypt_string(self, enc):
  22. enc = base64.b64decode(enc)
  23. return self.decrypt(enc).decode('utf8')
  24. encrypt = "P37w+VZImNgPEO1RBhJ6RtKl7n6zymIbEG1pReEzghk="
  25. cipher = AESCipher("test key")
  26. print("明文:\n{}".format(cipher.decrypt_string(encrypt)))
  27. # 明文:hello world复制

C

  1. using System;
  2. using System.Linq;
  3. using System.Security.Cryptography;
  4. using System.Text;
  5. namespace decrypt
  6. {
  7. class AESCipher
  8. {
  9. const int BlockSize = 16;
  10. private byte[] key;
  11. public AESCipher(string key)
  12. {
  13. this.key = SHA256Hash(key);
  14. }
  15. public string DecryptString(string enc)
  16. {
  17. byte[] encBytes = Convert.FromBase64String(enc);
  18. RijndaelManaged rijndaelManaged = new RijndaelManaged();
  19. rijndaelManaged.Key = this.key;
  20. rijndaelManaged.Mode = CipherMode.CBC;
  21. rijndaelManaged.IV = encBytes.Take(BlockSize).ToArray();
  22. ICryptoTransform transform = rijndaelManaged.CreateDecryptor();
  23. byte[] blockBytes = transform.TransformFinalBlock(encBytes, BlockSize, encBytes.Length - BlockSize);
  24. return System.Text.Encoding.UTF8.GetString(blockBytes);
  25. }
  26. public static byte[] SHA256Hash(string str)
  27. {
  28. byte[] bytes = Encoding.UTF8.GetBytes(str);
  29. SHA256 shaManaged = new SHA256Managed();
  30. return shaManaged.ComputeHash(bytes);
  31. }
  32. public static void Main(string[] args)
  33. {
  34. string encrypt = "P37w+VZImNgPEO1RBhJ6RtKl7n6zymIbEG1pReEzghk=";
  35. AESCipher cipher = new AESCipher("test key");
  36. Console.WriteLine(cipher.DecryptString(encrypt));
  37. }
  38. }
  39. }复制

Node.js

  1. const crypto = require("crypto");
  2. class AESCipher {
  3. constructor(key) {
  4. const hash = crypto.createHash('sha256');
  5. hash.update(key);
  6. this.key = hash.digest();
  7. }
  8. decrypt(encrypt) {
  9. const encryptBuffer = Buffer.from(encrypt, 'base64');
  10. const decipher = crypto.createDecipheriv('aes-256-cbc', this.key, encryptBuffer.slice(0, 16));
  11. let decrypted = decipher.update(encryptBuffer.slice(16).toString('hex'), 'hex', 'utf8');
  12. decrypted += decipher.final('utf8');
  13. return decrypted;
  14. }
  15. }
  16. encrypt = "P37w+VZImNgPEO1RBhJ6RtKl7n6zymIbEG1pReEzghk="
  17. cipher = new AESCipher("test key")
  18. console.log(cipher.decrypt(encrypt))
  19. // hello world
  20. 复制
    目录
  • 加密算法
  • 解密算法
  • PHP
  • Java
  • Golang
  • Python
  • C
  • Node.js
最新修改于:2022-02-17