BSN-DID研究6--客户端生成DID的计算方法

DID研究的第一步就是为用户生成DID标识符, 在帮助文件 14.2 HTTP API · BSN中说明了计算方法,
在SDK代码中 com.reddate.did.sdk.util.DidUtils类提供了生成函数。
1 创建DID过程介绍
有两个方式创建DID, 一种是在服务端创建,然后返回给前端。 另一种是在前端直接创建。 BSN-DID服务支持这两种方法。
//使用服务端创建DID
DidDataWrapper didData = didClient.createDid(false);
String did = didData.getDid();
因为创建DID必须使用公私钥信息,为了安全起见,一般用户多选择在前端(本地)生成公私钥然后计算生成DID,而不会把公私钥发送到服务端去计算。开发者可按下述介绍在本地完成开发。
1)通过椭圆曲线算法Secp256k1生成两对公私钥信息;
2)保存私钥,指定主备公钥拼装Base DID Document,其内容如下示例:
{
   "@context": "https://w3id.org/did/v1",
   "authentication":
   {
      "type": "Secp256k1",
      "publicKey": "28986472722394106073871327423452879123214061743224210681401278929598807211140001274507530324221923795865447680836742348963337343510229880669968499735858"
   }
   "recovery":
   {
      "type": "Secp256k1",
      "publicKey": "9251971168042915941551574641987721503984542761641852064853964541181378832746959340151297908312616596971625573967556676367696067937171601766581709843378481"
   }
}
3)通过base58(ripemd160(sha256()))算法生成DID标识符,其格式如下示例:
did:bsn:3wxYHXwAm57grc9JUr2zrPHt9HC
4)拼装DID Document内容,如下示例:
{
   "did": "did:bsn:3wxYHXwAm57grc9JUr2zrPHt9HC",
   "version": 1,
   "created": "2021-05-20T16:02:20Z",
   "updated": "2021-05-20T16:02:20Z",
   "authentication":
   {
      "type": "Secp256k1",
      "publicKey": "28986472722394106073871327423452879123214061743224210681401278929598807211140001274507530324221923795865447680836742348963337343510229880669968499735858"
   }
   "recovery":
   {
      "type": "Secp256k1",
      "publicKey": "9251971168042915941551574641987721503984542761641852064853964541181378832746959340151297908312616596971625573967556676367696067937171601766581709843378481"
   }
}
5)使用主私钥对DID Document内容进行Secp256k1签名,最终形成带有签名属性的DID Document,如下示例:
{
   "did": "did:bsn:3wxYHXwAm57grc9JUr2zrPHt9HC",
   "version": 1,
   "created": "2021-05-20T16:02:20Z",
   "updated": "2021-05-20T16:02:20Z",
   "authentication":
   {
      "type": "Secp256k1",
      "publicKey": "28986472722394106073871327423452879123214061743224210681401278929598807211140001274507530324221923795865447680836742348963337343510229880669968499735858"
   }
   "recovery":
   {
      "type": "Secp256k1",
      "publicKey": "9251971168042915941551574641987721503984542761641852064853964541181378832746959340151297908312616596971625573967556676367696067937171601766581709843378481"
   }
   "proof":
   {
      "type": "Secp256k1",
      "creator": "did:bsn:3wxYHXwAm57grc9JUr2zrPHt9HC",
      "signatureValue": "zD5nt+P/Ga/CRG2hJU/SMRXy210CLdvATsxQdPxTEy9Mc9Y0OSFpE3Yu5k2+OjQKVOtu5of9VFbgO3Zljw/vQxs="
   }
}
2 DidUtils类中函数解析
// 根据主备公钥拼装Base DID Document
public static BaseDidDocument generateBaseDidDocument(KeyPair primaryKeyPair, KeyPair alternateKeyPair)
//从一个完整的DOC中解析出Base DID Document
public static BaseDidDocument generateBaseDidDocument(final DidDocument didDocument)
// 根据base DID Document计算DID
public static String generateDidIdentifierByBaseDidDocument(BaseDidDocument baseDidDocument)
//含义没搞清楚
public static String generateDidByDidIdentifier(String didIdentifier)
//指定主备公钥DID,生成DOC
public static DidDocument generateDidDocument(KeyPair primaryKeyPair, KeyPair alternateKeyPair, String did)
关键的是看这两个函数:
/**
* Generate base did document
*
* @param primaryKeyPair
* @param alternateKeyPair
*/
public static BaseDidDocument generateBaseDidDocument(KeyPair primaryKeyPair, KeyPair alternateKeyPair)
      throws Exception {
   BaseDidDocument baseDidDocument = new BaseDidDocument();
   baseDidDocument.setContext(CurrencyCode.W3C_FORMAT_ADDRESS);
   PublicKey primaryPublicKey = new PublicKey();
   primaryPublicKey.setType(ECDSAUtils.TYPE);
   primaryPublicKey.setPublicKey(primaryKeyPair.getPublicKey());
   baseDidDocument.setAuthentication(primaryPublicKey);
   PublicKey alternatePublicKey = new PublicKey();
   alternatePublicKey.setType(ECDSAUtils.TYPE);
   alternatePublicKey.setPublicKey(alternateKeyPair.getPublicKey());
   baseDidDocument.setRecovery(alternatePublicKey);
   return baseDidDocument;
}
/**
* Generate did identifier (encode the base did document after hashing twice)
*
* @param baseDidDocument
*/
public static String generateDidIdentifierByBaseDidDocument(BaseDidDocument baseDidDocument) throws Exception {
   String baseDidDocumentStr = JSONArray.toJSON(baseDidDocument).toString();
   // Coding base did with sha256
   byte[] firstHashBaseDidDocument = SHA256Utils.getSha256(baseDidDocumentStr);
   // On this basis, ripemd160 coding is carried out
   byte[] secondHashBaseDidDocument = RipeMDUtils.encodeRipeMd160(firstHashBaseDidDocument);
   // Finally, base28 coding is carried out
   String afterEncodeBaseDidDocument = Base58Utils.encode(secondHashBaseDidDocument);
   return afterEncodeBaseDidDocument;
}
上面代码说明了计算步骤,  第一步sha256计算hash,第二步RipeMd160计算hash,第3步Base58。
【特殊说明1】 Base58Utils类的算法有特殊性。 我测试了,同样的字符串,Base58Utils.encode的结果与一般的base58在线计算工具计算结果不一样。这一点什么原因就没有去分析内部代码啦。
【特殊说明2】 KeyPair生成公钥和私钥字符串也和一般的钱包工具生成结果不同。
一般的钱包工具生成的公私钥是16进制形式的字符串:
例如  私钥: 5fb92d6e98884f76de468fa3f6278f8807c48bebc13595d45af5bdc4da702133
而KeyPair生成私钥是: 59892406425224321141687523581481793923894983609789633294227503636425859954495
这个字符串是10进制的大整数,因此具体应用时要注意区分转换。
【特殊说明3】baseDocument中填写的公钥字符串是10进制的大整数, 切记不要搞错了。
3 测试代码
我写了一段测试代码,验证目的:
(1)手工拼装的baseDocument字符串与自动生成的字符串相同
(2)计算出did
//先生成两组私钥:
主私钥
privateKey  59892406425224321141687523581481793923894983609789633294227503636425859954495
publicKey   1648062039648339302524063279508895632770137069244278134081956539023412707736391318756182919431261356264811228156011285063580540937190422178407117759695197
备私钥
privateKey  99212890707702586423403586560516123688816915830506844876534947464669890270173
publicKey   4066670788180339434818057706073753563728493176529383949647043421305103177112833274244990482553429820005190263150190403413261964491159960007274805620197902
//测试代码
public static void createMyDid(){
    DidDataWrapper didData = didClient.createDid(false);
    String did = didData.getDid();
    String  baseDoc =
            "{\"context\":\"https://w3id.org/did/v1\"," +
                    "\"recovery\":" +
                    "{" +
                    "\"publicKey\":\"4066670788180339434818057706073753563728493176529383949647043421305103177112833274244990482553429820005190263150190403413261964491159960007274805620197902\"," +
                    "\"type\":\"Secp256k1\"" +
                    "}," +
                    "\"authentication\":" +
                    "{" +
                    "\"publicKey\":\"1648062039648339302524063279508895632770137069244278134081956539023412707736391318756182919431261356264811228156011285063580540937190422178407117759695197\"," +
                    "\"type\":\"Secp256k1\"" +
                    "}" +
                    "}";
    System.out.println("baseDoc = "+baseDoc);
    String sha = SHA256Utils.getSha256String(baseDoc);
    System.out.println("sha = "+ sha);
    BaseDidDocument base = new BaseDidDocument();
    base.setContext("https://w3id.org/did/v1");
    PublicKey authentication = new PublicKey();
    authentication.setPublicKey("1648062039648339302524063279508895632770137069244278134081956539023412707736391318756182919431261356264811228156011285063580540937190422178407117759695197");
    authentication.setType("Secp256k1");
    base.setAuthentication(authentication);
    PublicKey recovery = new PublicKey();
    recovery.setPublicKey("4066670788180339434818057706073753563728493176529383949647043421305103177112833274244990482553429820005190263150190403413261964491159960007274805620197902");
    recovery.setType("Secp256k1");
    base.setRecovery(recovery);
    String baseDidDocumentStr = JSONArray.toJSON(base).toString();
    System.out.println("baseDidDocumentStr = "+ baseDidDocumentStr);
    sha = SHA256Utils.getSha256String(baseDidDocumentStr);
    System.out.println("sha = "+ sha);
    try {
        did = DidUtils.generateDidIdentifierByBaseDidDocument(base);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    System.out.println("did = "+ did);
}
运行结果:
baseDoc = {"context":"https://w3id.org/did/v1","recovery":{"publicKey":"4066670788180339434818057706073753563728493176529383949647043421305103177112833274244990482553429820005190263150190403413261964491159960007274805620197902","type":"Secp256k1"},"authentication":{"publicKey":"1648062039648339302524063279508895632770137069244278134081956539023412707736391318756182919431261356264811228156011285063580540937190422178407117759695197","type":"Secp256k1"}}
sha = f1fbda792c9d7bcc09b0e8c9024ae68af09880e421f9a21313f6fd7e76c893a0
baseDidDocumentStr = {"context":"https://w3id.org/did/v1","recovery":{"publicKey":"4066670788180339434818057706073753563728493176529383949647043421305103177112833274244990482553429820005190263150190403413261964491159960007274805620197902","type":"Secp256k1"},"authentication":{"publicKey":"1648062039648339302524063279508895632770137069244278134081956539023412707736391318756182919431261356264811228156011285063580540937190422178407117759695197","type":"Secp256k1"}}
sha = f1fbda792c9d7bcc09b0e8c9024ae68af09880e421f9a21313f6fd7e76c893a0
did = 4SdogXgSRXdetxH28SdJM5dydtKd
大功告成,最后生成了DID: 4SdogXgSRXdetxH28SdJM5dydtKd

猜你喜欢

转载自blog.csdn.net/u012084827/article/details/127175268