Wallet private and public keys | DIDs Decentralized Identifiers

Hello people from the land of wisdom,

I have a fairly straightforward question, is it possible to obtain the signing key of a wallet during a transaction?

I have this idea in mind and I was wondering if it’s possible to obtain the key or a hashed/serialized version of the signing key prior authorization of the wallet owner. Lets say during the “sign transaction” (authorization) process while the wallet is constructing and submitting the transaction.

If anybody knows about this or there’s maybe a similar process to do this, please share some love!

Thank you! :rocket:

For whom to get the key how?

If you have the seed phrase of a wallet you can always get the signing keys. (There is not the signing key of a wallet/account, but there are different signing keys per address plus typically one for the stake address.)

The wallet apps usually don’t store the seed phrase, but the master key derived from the seed phrase, encrypted by the spending password that they do not save. After the user has given the spending password, they can also derive all the signing and verification keys without problem.

But there is no interface or API to ask the wallet apps for signing keys. You’d have to go in the code. And then, it is not really important that you are in the process of signing a transaction, you could just ask the user for the spending password and derive the keys independently.

If you have a hardware wallet, the signing key never leaves the hardware device. The wallet app does not get to know it, but it asks the device to sign the transaction.

The public/verification keys on the other hand are contained in the signed transaction and could be extracted from it prior to submitting it.

If you do not use a seed phrase or hardware wallet, but single key files as when using cardano-cli in its simplest form, the keys are just there in the .skey and .vkey files.

1 Like

Hey Sean,

Thank you for taking the time! Well, in that case, can wallets created using single key files be imported into existing wallets like Yoroi or Flint? The reason is, I’m exploring the possibility of encrypting data using the private and public keys from wallets generated using the cardano-cli.

Essentially, only the legitimate owner of the wallet is allowed to decrypt data associated with that token. Therefore the encrypted data is still “locked” If the metadata (linked to some ADA) is transferred to another wallet due to the encryption being done using the .skey of the original wallet.

No, you cannot import single key files into a wallet.
If you want to have a Eternl/Flint/Yoroi wallet and also have the signing keys for it, why don’t you generate the wallet in cli starting from a recovery phrase and then also import it into Eternl/Flint/Yoroi?

2 Likes

As @georgem1976 said: The usual wallet apps only have support for seed phrases and hardware wallets, but not for key files, but you can get key files from seed phrases with cardano-address.

I don’t understand that. Which token? And metadata is not linked to ADA. It is linked to transactions and cannot be transferred between wallets. But by convention metadata for NFTs is searched at their minting transactions. And NFTs can be transferred to other wallets.

But, yes, if something is encrypted for the previous holder of an NFT, that encryption, of course, doesn’t automatically get updated if the token is sent to someone else. And encryptions also cannot be revoked. Even if the new holder gets access, you cannot take it from the previous holder cryptographically.

Depending on what exactly you want to do:
The address currently holding an NFT can be queried from the chain quite easily.
The public key of that address is maybe available (if there already has been a transaction from that address), maybe not (as long as there was no transaction, the public key is only known to the wallet owner, since the address only contains a hash of the public key).
A dApp could get the public key of an address by asking the wallet app to sign some data with https://cips.cardano.org/cips/cip30/#apisigndataaddraddresspayloadbytespromisedatasignature. The answer will contain the public key.

There is some standardisation of encryption found in https://cips.cardano.org/cips/cip8/#encryption, but I’m not aware of any wallet app implementing that. So, you maybe can just roll your own.

@ATADA has implemented the signing and verification part in https://github.com/gitmachtl/cardano-signer, but I don’t see the encryption and decryption part there.

1 Like

cardano-signer can sign and verify signatures with cardano secret/public keys. also you can construct signings via the cip-8 mode or cip-36 but without encryption/decryption.

cardano-signer itself does not offer any encryption or decryption functions.

you can maybe base your encryption on the proof of the signature.

there is a new derivation path for the governance vote key, its not a good idea to implement a method where people have to sign data with there payment key. also hw-wallets will never support signing arbitrary hex data with a secret key.

The whole idea is to encrypt arbitrary data using the public/private keys from a wallet. I was thinking of using the .skey and .vkey of a wallet generated by the cardano-cli although as @HeptaSean mentioned, these cannot be imported into existing wallets (Flint, Yoroi, etc) and therefore it won’t provide a good user experience for people.

@georgem1976 I must say thank you for providing this script! I was indeed researching on cardano-address to generate wallets using seed phrases and this script is literally everything I could wish for! haha, I really appreciate it.

@HeptaSean

The wallet apps usually don’t store the seed phrase, but the master key is derived from the seed phrase, encrypted by the spending password that they do not save. After the user has given the spending password, they can also derive all the signing and verification keys without a problem.

I think this is the user flow that we are looking for, we can imagine an “Encrypted NFT” (It could be something else but let’s just say it’s an NFT) and to decrypt this data, the wallet will ask for the spending password. It will derive the master key, which was used to encrypt the data originally, and decrypt the data afterward. This ensures an authorization layer by the user before decrypting the data.

Let me know if I missed anything or if I’m wrong in any of this (which most likely I am lol :laughing: )

1 Like

How do you want to do that? I don’t quite understand.

Also: CIP-8 already specifies encryption, doesn’t it?

Hmm, CIP-30 supports exactly that.

Yes, I do understand that in the “addresses are only used once” scheme, it was meant as an additional security measure that the public key is not even public until the only UTxO that will ever be on that address is spent, but that is already thrown out by all the single-address mode wallet apps that are around now. And the security of Ed25519 should really not depend on the public key not being public or used only once.

1 Like

Yes exactly. Public keys are meant to be public! It’s like saying that Instagram handles aren’t supposed to be public!

If it is an NFT, there is the additional thing that it has to be encrypted before the owner is known, when the NFT is minted. But that’s not that huge of a problem, since most asymmetric encryption schemes are hybrid anyway, encrypting the payload symmetrically and just transmitting the key asymmetrically encrypted. So, you could save the symmetric key and encrypt it for the specific owner later.

This would require people to give you the public key of the whole account. Not a huge security risk, especially if it is not the extended public key, but something that not everybody will want to do.

Why not use the public key of the address that holds the NFT?

1 Like

@HeptaSean This is the key!

it has to be encrypted before the owner is known

If we can encrypt arbitrary data and mint the NFT into a wallet that was programmatically generated with seed phrases, then we can provide this seed phrase to the future owner of this wallet (We don’t know who this is). The owner can later import this address to existing wallets like flint or yoroi, and access its encrypted NFT on demand.

If necessary, the NFT can be decrypted by asking for the spending password of the wallet owner. What do you think?

First thought: None of the wallet apps implements encryption and decryption up to now. So, if you do not want to send your prospective users to the command line doing cryptic stuff, it would need to become a CIP to extend the functionality of wallet apps (and probably also the CIP-30 dApp connector).

Second thought: You’d want to have hardware wallets support this somehow or else no Ledger or Trezor users could use it. Will make the path to adoption of such a CIP even harder.

That sounds kind of hackish to me. It’s the idea of NFTs that we can transfer them from wallet to wallet, from address to address. So, it would be odd if the encryption of the NFT keeps bound to this original (pseudo) wallet.

My idea would be:

  • Content c is encrypted with symmetric key k to get senc(k,c). senc(k,c) is stored on IPFS or similar.
  • When the NFT is minted to an address, we either ask for the public payment key or for a dedicated public utility key of the wallet and asymmetrically encrypt the symmetric key with it: aenc(pub,k) is stored in the transaction metadata.
  • The wallet owner has the private key for that and can decrypt adec(prv,aenc(pub,k))=k and then sdec(k,senc(k,c))=c and get the content.
  • When the NFT shall be transmitted to the next wallet the current owner requests the public key pub’ of the future owner and re-encrypts the symmetric key: aenc(pub’,adec(prv,aenc(pub,k)))=aenc(pub’,k) and stores it in the transaction metadata. And then the new owner has the same possibilities as the former owner.

Caveats:

  • Each former owner keeps the access to the keys forever. Not that big of a caveat, since they could also just have stored the decrypted content somewhere. Cannot be avoided.
  • If a wallet app is not aware of this whole process, it could transfer the NFT from wallet to wallet without this re-encryption and the new owner would not get access. Probably needs some protocol to ask the former owner after the fact (or any of the former owners including the creator?).
  • Wouldn’t work through dApps. They more or less by definition cannot have any secrets, so also no private keys.

So, maybe these would even be two CIPs: One for the primitives that wallet apps have to implement to allow encryption and decryption of payloads in general and some extensions to CIP-30, so that dApps can use that functionality, and one for the specific protocol for encrypted NFTs and their transfer.

1 Like

CIP-8 on its own does not require any encryption parts. Like sundaeswap used it right now or for the summit voting. With the Signature1 methode. No Encryption/Decryption involved.

I know that it’s not required, but it is specified, written down there how encryption should be done. Has anyone ever implemented that? Is it worth the effort to follow CIP-8 there?

Awesome view! This is exactly why we need to have this conversation and I feel @HeptaSean you are already going in the right direction. That’s the reason I said “let’s imagine its an NFT” but it actuality it is not.

The whole idea revolves on DIDs (Decentralized identifiers) and therefore only the original owner of the wallet is the only one allowed to access its own information that can carry certain sensitive information like the date of birth and more.

In reality there’s no consensus on DIDs although there’s already an standard for web3. That’s the reason we do need to push CIPs specifically for this. I already put a comment related to this subject over this CIP based on some research and ideas that are out there already. CIP-0066? | NFT Identity by Padierfind · Pull Request #294 · cardano-foundation/CIPs · GitHub

Of course, after this conversation I would dramatically changed my original comment although I feel we’re going in the right direction.

Following the web3 standard for DIDs ; A DID is a simple text string consisting of three parts: 1) the did URI scheme identifier, 2) the identifier for the DID method, and 3) the DID method-specific identifier. Also, a DID document contains information associated with the DID, such as ways to cryptographically authenticate a DID controller.

DID method-specific identifier can be the CBORHex serialized wallet address, following this schema

image

DID Document (JSON package) that lives in IPFS

ipfs://QmPPrHGV5UeG7YB9YJ1sVMhvb3NCtjPPFg8ksCtHWzuFVh

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://w3id.org/security/suites/ed25519-2020/v1"
  ]
  "id": "did:example:<CBORHEX_paymentaddress>",
  "issuer": "did:example:456", # https://bakrypt.io DID's 
  "payload": {
      "type": "DRIVERS_LICENSE",
      "expiration": "2022-11-07 22:51:39.964233" # We can use a better format for this
   },
  "authentication": [{
    
    "id": "did:example:<CBORHEX_paymentaddress>#keys-1",
    "type": "Ed25519VerificationKey2020",
    "controller": "did:example:<CBORHEX_paymentaddress>",
    "publicKeyMultibase": "5820d84d47b1eecc9efc6008a65a7e179a8da8d7d5fe050b6ca3bfffe360d19f88a7"
  }]
}

Data Structure for minted DIDs in the Cardano blockchain

{
  "<DID_metadatum_label>": {
    "subject": <CBORHEX_paymentaddress>,
    "document": "ipfs://QmPPrHGV5UeG7YB9YJ1sVMhvb3NCtjPPFg8ksCtHWzuFVh"
  }
}

In the future, wallets like Flint or Yoroi could filter DIDs based on the metadatum label for DIDs and show a list of encrypted identifiers that could publicly show the expiration date of each “token”. These DIDs documents can be decrypted by requesting the user for the spending password, only if its necessary.

I think i have not seen a public implementation with encrypted cip-8 data yet. I am planing to include it in cardano-signer, but scheduled for later one. One day has only so much hours. :rofl:

1 Like

Okay, then I don’t get at all, why you want encryption.

In all SSI concepts that I have seen so far, the DID document does not contain personal information. The personal information is in Verifiable Credentials (VCs, https://www.w3.org/TR/vc-data-model/) and those are not supposed to be living on a blockchain, but shall be carried around in personal wallets.

There already is https://iamx.id/ building an SSI infrastructure on Cardano (in fact, the one NMKR already uses and probably had in mind when drafting the CIP you were commenting on) and there will be Atala Prism (although they haven’t released their DID method to https://www.w3.org/TR/did-spec-registries/#did-methods up to now – in contrast to IAMX).

I am not really sure how successful yet another Cardano DID method would be. I would at least wait until a little more is known about how Atala Prism wants to do it and how the integration into Lace will look like which is also already announced. If they are doing everything horribly wrong (which I would not exclude), a concurrent concept can still be proposed.

I just saw that your idea of including “payload” in the DID document stems from the CIP draft. There already is a comment in the PR discussion that that is very non-SSI-like, since DIDs should not contain any personal information.

Moreover, you use the payment address as a method-specific identifier. For longer-living DIDs that is not really a good idea, since you will want to retire and replace keys.

Actually, the did:key method (https://w3c-ccg.github.io/did-method-key/) does exactly the same – using the public key itself as identifier, but it is specifically designed for short-term uses: “For example, a DID that will only be used for a single, ephemeral interaction might not need to be registered, updated, or deactivated, or where private keys are protected by software or hardware isolation. These are a few of the cases where using did:key might offer unique benefits.” And that method does not need a DID document to be stored anywhere. The document is just generated from the key. Much more light-weight.

This could be somehow reunited with Cardano wallets by generating such a key from a Cardano wallet and then using the did:key method. But that would be an additional functionality of the wallet app that does not have much if any interaction with the Cardano blockchain and does not need it.

This still has the problem that hardware wallets are excluded, until they provide a way to sign/decrypt arbitrary data, which may well never be the case. Could be a point for completely separating the wallet and keys used for identity management from the Cardano wallet.

Finally, the SSI on blockchain, SSI on Cardano people could not really convince me, why we want to use a blockchain at all for SSI. Methods like did:web (https://github.com/w3c-ccg/did-method-web), did:dns (https://danubetech.github.io/did-method-dns/, and did:ipid (https://did-ipid.github.io/ipid-did-method/) exist and seem to work perfectly well for publishing DIDs.

Yes, I saw what they have. What I’m proposing is a specific use case for DIDs.

What I’ve seen so far in terms of user verification is that there’s a dependency on the issuer to verify the document every time it’s needed by the verifier. Which makes the whole thing very hard to implement because we would depend on the government or organization to create technology to verify the document.

What I’m proposing is to mint a verification certificate based on KYC user flows which are done using credit bureaus. Therefore, whatever document you just verified is a valid representation of the document, not the actual document per se (Verification Certificate), and it’s up to the wallet owner to give authorization to a wallet to decrypt any information from the verification certificate, which this does not include your address nor your date of birth but rather a score and type of documentation of the verification procedure.

There are already many companies that do this type of work every day, like employment verification and criminal background checks whenever you apply for an apartment for example. It’s about leveraging the existing technology and integrating with Cardano blockchain

@HeptaSean

Okay, then I don’t get at all, why you want encryption.

Encryption is used to depend on the user or wallet owner rather than the issuer of the VC

No, that’s not the case. Cf. this illustration from https://www.w3.org/TR/vc-data-model/:
ecosystem
The issuer signs the credential only once (using their DID), gives it to the holder who stores it in local storage and presents it to verifiers. The verifiers just have to check the DIDs of holder and issuer using whatever DID methods and registries they used. No need to contact the issuer.

According to the whitepaper https://iamx.id/wp-content/uploads/2022/08/IAMX_white_paper_compressed.pdf, IAMX wants to use telecommunication providers and machine-readable government identity documents for that purpose, which seems a little less spooky than credit bureaus.

As said, that part is not needed in the usual SSI architectures, since the VCs are stored locally and the holder can just decide, which VCs to even present.

I still fail to see what purpose the integration with a blockchain or specifically the Cardano blockchain shall serve.