Creating public PASETO token in ASP NET Core

I'm using Paseto.Core Nuget from https://github.com/daviddesmet/paseto-dotnet, and I'm trying to create v4 public PASETO token with this. My code:

public async Task<TokenResponse> GenerateAsync(Client client, TokenRequest tokenRequest, string issuer, string audience)
    {
        var privateEd25519Key = await File.ReadAllBytesAsync("private.pem");

        var pasetoToken = new PasetoBuilder()
            .Use(ProtocolVersion.V4, Purpose.Public)
            .WithKey(privateEd25519Key, Encryption.AsymmetricSecretKey)
            .Issuer(issuer)
            .Subject(tokenRequest.ClientId)
            .Audience(audience)
            .NotBefore(DateTime.UtcNow)
            .IssuedAt(DateTime.UtcNow)
            .Expiration(DateTime.UtcNow.AddSeconds(client.AccessTokenLifetime))
            .TokenIdentifier(Guid.NewGuid().ToString())
            .AddClaim("client_id", tokenRequest.ClientId)
            .AddClaim("scopes", tokenRequest.Scopes)
            .Encode();

        return new TokenResponse
        {
            AccessToken = pasetoToken,
            Lifetime = client.AccessTokenLifetime,
            Scope = tokenRequest.Scopes
        };
    }
}

I get an error all the time:

System.ArgumentException: expandedPrivateKey.Count
   at Paseto.Cryptography.Ed25519.Sign(ArraySegment`1 signature, ArraySegment`1 message, ArraySegment`1 expandedPrivateKey)
   at Paseto.Cryptography.Ed25519.Sign(Byte[] message, Byte[] expandedPrivateKey)
   at Paseto.Protocol.Version4.Sign(PasetoAsymmetricSecretKey pasetoKey, String payload, String footer, String assertion)
   at Paseto.Handlers.PasetoPublicPurposeHandler.Sign(IPasetoProtocolVersion protocol, String payload, String footer, String assertion)
   at Paseto.Builder.PasetoBuilder.Encode()

Besides, due to the rather unclear documentation, I don't know if I'm really creating a token signed with a private key or encrypted.

1 answer

  • answered 2022-05-07 18:31 Szyszka947

    Here is my solution:

    public async Task<TokenResponse> GenerateAsync(Client client, TokenRequest tokenRequest, string issuer, string audience)
        {
            var ed25519pkcs8 = await File.ReadAllTextAsync("private.pem");
    
            var privatePemReader = new PemReader(new StringReader(ed25519pkcs8));
            var ed25519pkcs8Parameters = (Ed25519PrivateKeyParameters)privatePemReader.ReadObject();
            ISigner signer = new Ed25519Signer();
            signer.Init(true, ed25519pkcs8Parameters);
    
            var pasetoToken = new PasetoBuilder()
                .Use(ProtocolVersion.V4, Purpose.Public)
                .WithKey(signer.GenerateSignature(), Encryption.AsymmetricSecretKey)
                .Issuer(issuer)
                .Subject(tokenRequest.ClientId)
                .Audience(audience)
                .NotBefore(DateTime.UtcNow)
                .IssuedAt(DateTime.UtcNow)
                .Expiration(DateTime.UtcNow.AddSeconds(client.AccessTokenLifetime))
                .TokenIdentifier(Guid.NewGuid().ToString())
                .AddClaim("client_id", tokenRequest.ClientId)
                .AddClaim("scopes", tokenRequest.Scopes)
                .Encode();
    
            return new TokenResponse
            {
                AccessToken = pasetoToken,
                Lifetime = client.AccessTokenLifetime,
                Scope = tokenRequest.Scopes
            };
        }
    

    It turned out that WithKey doesn't support PEM files, so you had to get the private key out of PKCS#8.

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum