brenodacosta
brenodacosta

Reputation: 640

Issue with Inconsistent DID and VerKey Lengths Using DidSigner in Indy Plenum

I'm working on a project with Indy Plenum, and I encountered an issue with generating DIDs and verification keys. I'm using the following function to generate them from a 32-character seed:

import sys
import argparse
from plenum.common.signer_did import DidSigner

def generate_did_verkey(seed: str):
    """
    Generate DID and verification key using the provided seed.
    
    Args:
        seed (str): A 32-character long seed value.

    Returns:
        tuple: A tuple containing the DID and verification key.
    """
    if len(seed) != 32:
        raise ValueError("The seed must be exactly 32 characters long.")
    
    seed_value = seed.encode()
    signer = DidSigner(seed=seed_value)
    did = signer.identifier
    verkey = signer.verkey

    return did, verkey

Even though I'm passing a seed that is exactly 32 characters long, the DidSigner class in Indy Plenum sometimes gives me a DID that is 22 characters long (which is expected and works), but other times it gives me a 21-character DID, which causes issues later when I try to use it with an Indy node function (throws an error due to invalid DID length).

Similarly, the verification key (verkey) is sometimes 23 characters (correct), but occasionally it gives me a 22-character verkey, which also causes problems down the line.

I’m not sure why the lengths of the DIDs and verkeys are inconsistent when the input seed is always 32 characters. I created a small script to call generate_did_verkey(seed) 10 times with random seeds, and here are the results:


Test Results:

root@indy-pool-4-nodes-node-1-79bf89ccd6-b7gt4:/indy_node/indy_network# python3 test_get_did_and_verkey.py 
Seed 1: 6Tzxx5GR3VOqurfEzYhPmhyYgvGgdsPx
DID: GzbU6UywWsndZhov6aLVD9 (Length: 22)
VerKey: ~2TxDRQRCPrXQHiNdSq77Mt (Length: 23)

Seed 2: Jp8WBrwxHXn5YCVL2pNKwKwrJuxoQIjI
DID: 7yMvyQ3tcCYVgsid5ky9Nq (Length: 22)
VerKey: ~QDUxbkNknGdFidzQtPG758 (Length: 23)

Seed 3: zAgaUG7vK7ZFI5J4g4yUkB0rxAXNcNSO
DID: TmGcz2c5fdSjwuhmxpuJRg (Length: 22)
VerKey: ~M8dRGxpfHPpfWPUrkchpui (Length: 23)

Seed 4: 4AG44VWxPNkufirKFJztcjzv4VlgHN6B
DID: 6f8mNreThwNJ7AJ5xsaY73 (Length: 22)
VerKey: ~7MkCDmm5hxcwNd2VnmiB7V (Length: 23)

Seed 5: h01iyHIGs7wGr1TANq5cMOMfv30pRk5C
DID: 7fNPiLQjpmnQjGJ9KyCJc7 (Length: 22)
VerKey: ~7ewe36QjzNMkFAsKVtficY (Length: 23)

Seed 6: ZG6DxtYzVqQDXuNMsUzNAL6cjnTQqwmO
DID: 3vBqosKemC4M16pwQd3BR6 (Length: 22)
VerKey: ~HJvaYU3BtWJxHucaCbG9gK (Length: 23)

Seed 7: ZafyqLLqhENdJMfBOaFsKuz8OFRKpNv1
DID: N8mXH8kXon5P5nJ5KVQK53 (Length: 22)
VerKey: ~2suZ4eyHmVJwQdPmLDvoZs (Length: 23)

Seed 8: ONCWCJvCHO6speTaJU3JkGjEP51PoisD
DID: JdhBRD8B8NqDTBqbArZZ2e (Length: 22)
VerKey: ~3J7Sp26EGGUXbKD2fCCftp (Length: 23)

Seed 9: IXQ1sHoi5w3hLdX4FRJYB3qYdPJ6Cqgw
DID: rbTbLZs69hX1zRJnzHu8Q (Length: 21)
VerKey: ~N2H55kCg8LcTEC4Jqh7dJA (Length: 23)

Seed 10: qjJkRI0iGmqkM6CTgmFwZcrRqTAoWKHQ
DID: FDmCMrGuMFphpafEQopZWz (Length: 22)
VerKey: ~7XuxKGQEDzookBv6wZksxR (Length: 23)

Has anyone experienced this issue with DidSigner in Indy Plenum before? Is there something wrong with how I'm generating the DIDs or using DidSigner?

Upvotes: 1

Views: 42

Answers (1)

erenakyildiz
erenakyildiz

Reputation: 103

The DID generation function that uses your seed turns your seed into a Base58 value;

  • Base58 has some edge cases in which it can create extra bytes.

  • Base58 removes leading zeros in the binary input.

I had the same issue, I just check the string lengths and recreate the seed then rerun until the correct length's are found (My problem was ACA-PY's functions don't accept the incorrect length values, you might still be able to use the DID and Verkey's if you dont use ACA-PY, note, I have not tested this.).

When you call:

signer = DidSigner(seed=seed_value)
did = signer.identifier
verkey = signer.verkey

return did, verkey

First this is called signer_did.py:

 def __init__(self, identifier, verkey=None, rawVerkey=None):
    self.abbreviated = None
    if (verkey is None or verkey == '') and (rawVerkey is None or rawVerkey == ''):
        if identifier:
            self._identifier = identifier
            if (verkey is None and rawVerkey is None):
                self._verkey = None
            else:
                self._verkey = ''
            return

    if not ((verkey or rawVerkey) and not (verkey and rawVerkey)):
        raise ValueError(
            "Both verkey {} and rawVerkey {} can't be specified"
            .format(verkey, rawVerkey)
        )

    if identifier:
        self._identifier = identifier
        if rawVerkey:
            self._verkey = rawToFriendly(rawVerkey)
            self.abbreviated = False
        else:
            if verkey.startswith("~"):
                self._verkey = verkey[1:]
                self.abbreviated = True
            else:
                self._verkey = verkey
                self.abbreviated = False
    else:
        verraw = rawVerkey or friendlyToRaw(verkey)
        self._identifier = rawToFriendly(verraw[:16]) **#The issue comes from here.**
        self._verkey = rawToFriendly(verraw[16:]) **#Also might create an issue here.**
        self.abbreviated = True

Raw to friendly (utils.py)

def rawToFriendly(raw):
    return base58.b58encode(raw).decode("utf-8")

I think the problem arises from this function, you are hitting some edge cases.

Upvotes: 1

Related Questions