Emurgo / cardano-serialization-lib

This is a library, written in Rust, for serialization & deserialization of data structures used in Cardano's Haskell implementation of Alonzo along with useful utility functions.
Other
230 stars 124 forks source link

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

Closed JustLeif closed 6 months ago

JustLeif commented 7 months ago

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 commented 6 months ago

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 commented 6 months ago

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!