Skip to content

挑战应答接口

挑战接口

该接口用于获取挑战信息,为一随机nounce值

请求参数

  • 请求服务:企业节点业务系统HTTP端口(默认 3000)
  • 请求方式:GET
  • 请求路径:/api/v1/doip/public/challenge
  • Header:
参数类型是否必填最大长度备注示例值
Content-TypeString-application/jsonapplication/json
  • param:
参数类型是否必填最大长度备注示例值
handleString255要查询的标识88.111.911/app

请求示例

/api/v1/doip/public/challenge?handle=88.111.911/app

响应参数

名称类型必选约束中文名说明
codeintegertruenonenone返回码
messagestringtruenonenone返回消息
dataobjecttruenonenone返回数据

响应示例

json
{
  "code": 1,
  "message": "operation was successfully processed",
  "data": "1816"
}

异常示例

json
{
  "message": "标识格式异常",
  "code": 40508
}

注意事项

  1. 该接口只允许应用身份调用,其他身份调用无法获取nounce值。

应答颁发Token

该接口用于验证使用nounce值生成的signature,验证成功则颁发token

请求参数

  • 请求服务:企业节点业务系统HTTP端口(默认 3000)
  • 请求方式: POST
  • 请求路径: /api/v1/doip/public/verify-response
  • Header:
参数类型是否必填最大长度备注示例值
Content-TypeString-application/jsonapplication/json
  • Body:
名称位置类型必选说明
handlebodystring标识
signaturebodystring签名

返回数据结构

名称类型必选约束中文名说明
codeintegertruenonenone返回码
messagestringtruenonenone返回消息
dataobjecttruenonenone
data.tokenstringtruenonenone返回token

响应示例

json
{
 "code": 1,
 "message": "operation was successfully processed",
 "data": {
 "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI4OC42MDguODg4L0FwcF96ajAxIiwiZXhwIjoxNzAyNTQyMTM0LCJpYXQiOjE3MDI0NTU3MzQsImp0aSI6IjMxMzlmNDVkLTA5YzAtNDljZS04MTdkLWE4NDRhZmFlZTFjMyJ9.9Akw3pAwMM-tHZ6WOB6OI4E_ZMvDKyRn6CPYD1TWahc"
 }
}

异常示例

json
{
 "message": "标识格式异常",
 "code": 40508
}

签名生成方式参考

企业节点接口认证流程

企业节点OpenAPI认证使用挑战应答的方式,主体流程如下

img.png

签名生成

java
/**
 * 私钥签名
 * @param data
 * @param privateKey
 * @return
 * @throws Exception
 */
public static String sign(byte[] data, PrivateKey privateKey) throws Exception {
    // 用私钥对信息生成数字签名
    Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
    signature.initSign(privateKey);
    signature.update(data);

    return Base64.getEncoder().encodeToString(signature.sign());
    }

/**
 * 转换私钥格式
 */
public static PrivateKey fromPkcs8Pem(String pem) throws Exception {
      return fromPkcs8Pem(pem, null);
  }

/**
 * 转换私钥格式
 */
public static PrivateKey fromPkcs8Pem(String pem, String passphrase) throws Exception {
      BytesAndKeyType bytesAndKeyType = readPemFile(new StringReader(pem));
      boolean encrypted = "ENCRYPTED PRIVATE".equals(bytesAndKeyType.keyType);
      if (!encrypted && !"PRIVATE".equals(bytesAndKeyType.keyType)) {
          throw new Exception("Expected -----BEGIN [ENCRYPTED] PRIVATE KEY-----");
      }
      return privateKeyFromBytes(bytesAndKeyType.bytes, encrypted, passphrase);
  }
Python
#!/usr/bin/env python
#coding=utf-8
import os
import json
import base64
# RSA
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
  
# admin1-app1
path_to_private_key_pem_file = '//Users//graypig//Downloads//App_app100.pem'

nounce="1850"  ## 替换为challenge接口获取的随机数
byte_array_nonce = nounce.encode()
  
def sign_bytes_rsa( byte_array_nonce, path_to_private_key_pem_file):
	key = open(path_to_private_key_pem_file, 'r').read()
	rsa_key = RSA.importKey(key)
	signer = PKCS1_v1_5.new(rsa_key)
	_digest = SHA256.new()
	#print len(nounce)
	# print len(digest)
	_digest.update(byte_array_nonce)
	# _digest.update(digest)
	sign = signer.sign(_digest)
	#print len(sign)
	return base64.b64encode(sign)
  
sign = sign_bytes_rsa( byte_array_nonce, path_to_private_key_pem_file)
print(sign)

Released under the MIT License.