Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finding a Go library that can perform basic data signature validation. #656

Closed
JustLeif opened this issue Dec 17, 2023 · 2 comments
Closed

Comments

@JustLeif
Copy link

JustLeif commented Dec 17, 2023

I'm starting a project and I would like to write my backend in Go. I want to perform user authentication with a Cardano CIP-30 wallet. I used the Cardano documentation: https://developers.cardano.org/docs/integrate-cardano/user-wallet-authentication/ and I found this library with a JavaScript npm package to perform this validation.

I am not a cryptography expert and I don't currently understand the signature validation code in this library, I was wondering if anyone knows how I can best achieve this same code:

async function authenticate(req, res) {
    const sigData = req.body;
    const decoded = COSESign1.from_bytes( Buffer.from(sigData.signature, "hex") );
    const headermap = decoded.headers().protected().deserialized_headers();
    const addressHex = Buffer.from( headermap.header( Label.new_text("address") ).to_bytes() )
        .toString("hex")
        .substring(4);
    const address = Address.from_bytes( Buffer.from(addressHex, "hex") );

    const key = COSEKey.from_bytes( Buffer.from(sigData.key, "hex") );
    const pubKeyBytes = key.header( Label.new_int( Int.new_negative(BigNum.from_str("2")) ) ).as_bytes();
    const publicKey = PublicKey.from_bytes(pubKeyBytes);

    const payload = decoded.payload();
    const signature = Ed25519Signature.from_bytes(decoded.signature());
    const receivedData = decoded.signed_data().to_bytes();

    const signerStakeAddrBech32 = RewardAddress.from_address(address).to_address().to_bech32();
    const utf8Payload = Buffer.from(payload).toString("utf8");
    const expectedPayload = `account: ${signerStakeAddrBech32}`; // reconstructed message

    // verify:
    const isVerified = publicKey.verify(receivedData, signature);
    const payloadAsExpected = utf8Payload == expectedPayload;
    const signerIsRegistered = registeredUsers.includes(signerStakeAddrBech32);

    const isAuthSuccess = isVerified && payloadAsExpected && signerIsRegistered;

    res.send({
        success: isAuthSuccess,
        message: isAuthSuccess ? "✅ Authentication success!" : "❌ Authentication failed."
    })
}

In Go.

Thanks in advance :)

Edit:

Also if anyone knows of a clean way to perform user authentication without a 'data signature' then I would love to know alternate implementations.

@lisicky
Copy link
Contributor

lisicky commented Jan 15, 2024

To use CSL via Go you need to write a bridge between Go and Rust , example of bridge between rust and react-native you can see here https://github.com/Emurgo/csl-mobile-bridge you can leverage existing code to write your own bridge.
To prove wallet/staking_key/any_other_key ownership you need to provide a signature otherwise it would be very difficult to prove that you own it. Signatures is one of cornerstones of an blockchain

@JustLeif
Copy link
Author

To use CSL via Go you need to write a bridge between Go and Rust , example of bridge between rust and react-native you can see here https://github.com/Emurgo/csl-mobile-bridge you can leverage existing code to write your own bridge. To prove wallet/staking_key/any_other_key ownership you need to provide a signature otherwise it would be very difficult to prove that you own it. Signatures is one of cornerstones of an blockchain

Thanks for your help!

@lisicky lisicky closed this as completed Jan 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants