0

我正在尝试测试 PASETO 令牌,但遇到一个问题,我无法在前端正确验证令牌的有效性。由于我还没有找到任何用于检查签名的浏览器实现,因此我必须自己执行此操作,使用https://paseto.io/rfc/作为参考。使用的令牌类型是v2 public.

问题:

我编写的验证程序在某些情况下接受签名,但这取决于签名的有效负载。我是否会在生成新令牌之前将另一个键值对添加到有效负载或更改数据,验证者错误地说新令牌的签名无效。要查看实现,请检查下面的沙箱。

负载是否有我不知道的限制或要求?是否有我缺少的编码?还是我只是错误地实施了它并且不符合 PASETO 规范?任何指针都会有所帮助。

复制:

这个沙箱展示了我的实现和问题,带有不同有效负载的令牌,由相同的 ed25519 密钥签名: https ://codesandbox.io/s/paseto-decoder-lvk7r?file=/paseto.js

这是一个苗条的回购,因为这就是我将如何使用它。但重要的部分是paseto.js文件。

沙盒中使用的令牌是从项目的后端服务获得的,用 Go v1.14 编写:

import (
  "time"
  "encoding/hex"
  "myapplication/model"
  "github.com/o1egl/paseto".    //@v1.0.0
  "golang.org/x/crypto/ed25519" //@v0.0.0-20210421170649-83a5a9bb288b
)

func CreateToken(u *model.U, s *model.S) (string, error) {
  payload := paseto.JSONToken{
    IssuedAt:   time.Now(),
    Expiration: expiresAt,
  }
  footer := "AccessToken"
  
  // All following values are of type string 
  payload.Set("UserID", u.ID)
  payload.Set("Name", u.Name)
  payload.Set("Email", u.Email)
  payload.Set("SpotifyToken", s.AccessToken)

  // Secret from .env in my app, this private key is only for this question
  b, _ := hex.DecodeString("28451edefa6cb29ef7282fc65739b6dd29bb9c2c7ec4166d725252731f102e5c57ff822de765e6f5c566961be40b41f91726d958af2b53ca8dfce85d7d0c1940")
  privateKey := ed25519.PrivateKey(b)

  return paseto.NewV2().Sign(privateKey, payload, footer)
}

在后端的相同三个令牌上运行该paseto.NewV2().Verify()函数会导致所有令牌都有效,因此 Go 包验证方法的实现与我自己的 JavaScript 方法之间存在差异。

在这一点上,我不确定哪里出了问题,因为执行检查的实现太少了。正如我所看到的,它可能是我在 JS 中的验证方法、我用来创建令牌的 Go 包/实现,或者两者兼而有之。在这一点上,任何指向我在哪里弄乱不同编码或有什么问题的指针都将非常感激。

PS:这篇文章和沙箱中的任何秘密(例如令牌/密钥)在我的项目中都已失效。

4

1 回答 1

0

我相信您的问题可能与 JS 示例中使用的 base64 解码有关。

我有一个类似的问题导致我来到这里,但似乎有所不同。但是,我确实在我的代码中注意到 Paseto 规范要求使用 URLSAFE / NOPADDING base64 变体。

我看到您正在使用 Base64-JS 库,但我不确定默认情况下它将解码 Base64 的哪个变体,但这可能解释了为什么在向有效负载数据添加或删除密钥时有一些有效和错误。

我在前端令牌验证过程中使用了 libsodium 包装器,这是我为我的示例找到的一些相关的令牌解析部分......

        // sodium = require('libsodium-wrappers-sumo');
        let dec = new TextDecoder();
        let segments = signed_token.split('.');
        let f = segments.length == 4 ? dec.decode(sodium.from_base64(segments[3], sodium.base64_variants.URLSAFE_NO_PADDING)) : '';
        let msig = sodium.from_base64(segments[2], sodium.base64_variants.URLSAFE_NO_PADDING);

对此进行新的搜索再次出现了这个 repo https://github.com/jedisct1/js-base64-ct 在这里可能看起来很相关,对你来说也是如此。

于 2021-12-04T14:10:43.757 回答