Fail to verify delegation certificate

I tried to pass identity using the key file as below.

public async init(host: string, idlFactory: IDL.InterfaceFactory, canisterId: string, keyFile?: string) : Promise<void> {
        try {
            let identity = undefined;
            if (keyFile) {
                const rawKey = fs
                    .readFileSync(keyFile, 'utf8')
                    .toString()
                    .replace("-----BEGIN EC PRIVATE KEY-----", "")
                    .replace("-----END EC PRIVATE KEY-----", "")
                    .trim();
                    console.log(rawKey);
                // const rawBuffer = Buffer.from(rawKey, 'utf-8');

                // Convert the pem file to a sha256 hash
                const privKey = Uint8Array.from(sha256(rawKey, { asBytes: true }));

                // Initialize an identity from the secret key
                identity = Secp256k1KeyIdentity.fromSecretKey(
                    Uint8Array.from(privKey).buffer
                );
                console.log(identity.getPrincipal().toText());
            }
            const agent = new HttpAgent({ host, fetch: fetch as any, identity });
            
            // if (process.env.PRODUCTION === undefined || process.env.PRODUCTION !== 'prod') {
            //     await agent.fetchRootKey();
            // }

            this.actor = Actor.createActor(idlFactory,{
                agent,
                canisterId,
            });
        } catch (err) {
            return Promise.reject(err);
        }
    }

I’m getting an error fail to verify delegation certificate
I printed out the principle as well and the generated one is different than my actual principle id.
I really appriciate someone can help me to resolve this issue.

I tried quite a bit too (see this post) but did not manage to make it neither.

At the end of the day, if your goal is to reproduce itentities from dfx in agent-js, it might just unfortunately not be possible at the moment :point_right: Using @dfinity/agent in node.js - #39 by kpeacock

It’s definitely possible to get a reproducible identity from a PEM file, but reproducing the exact behavior from the Rust library used by dfx to parse .pem files takes a lot of work.

I suggest structuring your code with the assumption of multiple controllers or privileged users, and then using a separate identity in JS from your command line

Thanks for the reply @kpeacock. Actually, What I’m trying to do is that deploy a serverless application that interacts with the ICP

Any updates on this?

Could rust be an option for you for this project? Rust is often touted as the future of serverless, and for good reasons.

Thanks for the reply @GLdev. I wrapped a nestjs project inside my serverless application that has been written in Typescript. So using Rust maybe not be possible for me. Is there any other way to set identity in the javascript client?

I would go the route suggested in another post: create an arbitrary identity and add it in your ACL on the canister side, so you can accept messages from it. A new feature of dfx is that you can add multiple controllers, so that could also be done.

Basically with this new feature you shouldn’t need to add the exact same key from dfx to your serverless functions. You can use different identities and just add them as controllers / in the ACL

Could you share some useful resources with me?
Another quick question if you could help, I printed out the caller’s identity in a canister function in my local development environment and I called the function from Nodejs client by fetching the root key. It doesn’t match the principal id of mine. Why is that?

I was possible to generate the principle id as in the following post and generated a new identity using the keysmith tool. Use seeds example.

It’ll be very useful if someone can document these since a lot of developers facing the same kind of issues. Thank you very much for helping me guys.

1 Like