1736520198
2025-01-10 14:01:00
tl;dr – 開発者は当社の顧客であるため、開発者に美しい API キーを持たせたいと考えました。適切な標準ソリューションが見つからなかったので、独自のパッケージを作成しました。 uuidキー – UUID を人間が判読できるキーにエンコードおよびフォーマットするために使用できます。 UUIDv7 を使用する場合は、キーをデコードして、並べ替え可能でインデックス付け可能な ID としてデータベースに保存することもできます。
問題
API キーはユーザーの製品との最初のやり取りの大部分を占めており、良い印象を与えたいと考えています。私たちはキーの見栄えと「感触」を良くしたいと考えていますが、業界には「良い」基準がないようです。
私たちは多忙なスタートアップ企業ですが、開発者第一のプラットフォーム企業でもあります。したがって、私たちは、私たち (そして願わくば開発者) が満足できるソリューションを見つけるために、ある程度の時間と思考と努力を費やすことが理にかなっていると考えました。
ほとんどの API キーは役に立たない
API キーの要件のリストを作成しました。
- 安全な
- 世界的にユニークな
- ソート可能
- Postgres でのパフォーマンス
- 見ていてよかった
残念ながら、ほとんどの API キーは醜いものです。これらは多くの場合、書式が一貫していないランダムな文字列であるため、読み取り、並べ替え、識別が困難になります。

世に出回っている醜い API キー。
人生のほとんどの美しいものは対称的であるため、私たちは API キーに対称性をもたらしたいと考えました。

自然界における対称性。画像はBoredPandaから。
拒否された ID 🙅
ランダムすぎる、推測しやすい、醜すぎる…どれもそうではありませんでした ちょうどいい
予測可能すぎる、羊を順番に数えるようなもの 🐑
シンプルで読みやすく、並べ替えも簡単です。しかし、それらは存在するキーの数を明らかにし、簡単に推測できるため、セキュリティにとってはあまり良くありません。
時代を超越しすぎて、まるで針のない時計のよう ⏰
NanoID 完全にランダムなカスタマイズ可能な ID を提供します。これらは、一般向けの識別子に特に適しています (私たちはパブリック ID にも使用しています)1)。ただし、並べ替えやデバッグに役立つタイムスタンプ情報が不足しています。
id, _ := publicid.New()
fmt.Println("Generated default public ID:", id)
弊社を使用して生成された NanoID 公開 パッケージ。
汚すぎる、アルファベットのスープが間違ってしまったみたい🥄
UUID は業界標準であり、API キーについては 2 つのバージョンを検討する価値があります。2:
- UUIDv4: 純粋にランダムな文字。シンプルですが効果的です。
- UUIDv7: タイムスタンプが含まれています。これは次の理由で好まれます。
- 作成時間が埋め込まれており、データベースを検索せずにデバッグするのに役立ちます
- 効率的なデータベース クエリと時系列の並べ替えが可能になります。

全体として、開発者は UUID を使用することを好みますが、見た目が気に入らないだけです。

同様の苦情を持つ X ユーザー。
ほぼ完璧ですが、まだお粥の温度には達していません 🥣
ULID 私たちが求めていたものに近かったです。これらにはタイムスタンプが含まれており、読みやすさを高めるために Base32 エンコードが使用されています。しかし、私たちは UUID のネイティブ Postgres サポート (詳細は後述) を好みましたが、見た目の美しさにはまだ満足していませんでした。
私たちのソリューション
どのオプションも十分に美しく(対称的)なかったので、独自のアプローチを作成しました。
- UUIDv7 をベース ID として使用してタイムスタンプを利用する
- 読みやすくするために Crockford Base32 を使用して ID をエンコードします
- 美観を高めるために巧みに配置されたダッシュを追加する
結果:
key, _ := uuidkey.Encode("d1756360-5da0-40df-9926-a76abff5601d")
fmt.Println(key)
私たちのキーは次のとおりです。
- 31 文字 (ダッシュなしで 28 文字) 対 UUID の 36
- 7 つの大文字と数字を 4 セット含む可読性の高いセグメントにより、「ブロック状」の美しさと読みやすさを実現
- UUIDとしてデコードして保存すると、時系列に並べ替え可能
- ユーザー向けのキー内の難読化されたタイムスタンプ (ただし、知識のあるユーザーであればまだデコードできます)。キーにタイムスタンプ メタデータが含まれていると便利です。いつでも代わりに UUIDv4 を使用できます。やりますか、ブーイング! 👻
UUIDv7 を使用する理由
タイムスタンプの利点を超えて、UUIDv7 は v18 でネイティブ Postgres サポートを取得します。3。ご利用いただけるうちに 拡張子 現時点ではサーバー側で UUIDv7 を生成するため、ネイティブ Postgres サポートのパフォーマンスは確実に向上します。4に渡すのに最適です。 uuidkey.Encode()。
私たちの実装では、現在アプリケーション層でキーを生成し、それらを並べ替えとインデックス付けのために UUID として保存しています。 Postgres v18 がリリースされたら、Postgres 世代に切り替えて、アプリケーション層からデータフローをオフロードし、パフォーマンスを若干向上させる予定です。
なぜ Crockford Base32 なのか?
私たちが選んだのは クロックフォード ベース32 エンコードする理由は次のとおりです。
- 大文字と数字のみを使用するため、読みやすくなります。5
- キーの長さを約 1/5 に短縮します
- マッピングはパフォーマンスが高く、予測可能です
- クールな子供たちがみんな使っているものです 😎
なぜダッシュなのか?
結果の破線キーは「ブロック状」で対称的になります。個々の文字をグレーアウトすると、ほとんどバーコードのように見えます。これにより、キーの一部をすばやく読み取って識別することが容易になると考えられます。
私たちは無意識のうちに、昔ながらのプロダクト CD キーからインスピレーションを受けているのかもしれません。

戻ってきます…. 画像は eBay からのものです。
ダッシュを使用すると、ダブルクリックで簡単にコピーできなくなりますが、これは読みやすさとのトレードオフだと考えています。私たちは、ユーザーがこれらのファイルをどこにでもコピーして貼り付けることを望んでいません。実際、それらを慎重に扱ってほしいと考えています。理想的には、ユーザーはダッシュボードからキーを生成するときに各キーを 1 回だけコピーするため、そのケースを解決するために UI にコピー ボタンを追加しました。
の uuidkey パッケージ
これらの設計の選択肢をオープンソース化しました。 github.com/agentstation/uuidkey。私たちの美学、推論、対称性に同意し、独自の美しい API キーが必要な場合は、オープンソース プロジェクトを自由に試してみてください。
の心 uuidkey パッケージは UUID を読み取り可能な形式にエンコードします Key Base32-Crockford コーデック経由でフォーマットし、UUID にデコードし直します。
エンコード
func Encode(uuid string) (Key, error) {
if len(uuid) != UUIDLength {
return "", fmt.Errorf("invalid UUID length: expected %d characters, got %d", UUIDLength, len(uuid))
}
s1 := uuid[0:8]
s2 := uuid[9:13]
s3 := uuid[14:18]
s4 := uuid[19:23]
s5 := uuid[24:36]
n1, _ := strconv.ParseUint(s1, 16, 32)
n2, _ := strconv.ParseUint(s2+s3, 16, 32)
n3, _ := strconv.ParseUint(s4+s5[:4], 16, 32)
n4, _ := strconv.ParseUint(s5[4:], 16, 32)
e1 := encode(n1)
e2 := encode(n2)
e3 := encode(n3)
e4 := encode(n4)
return Key(e1 + "-" + e2 + "-" + e3 + "-" + e4), nil
}
デコード
func (k Key) Decode() (string, error) {
if len(k) != KeyLength {
return "", fmt.Errorf("invalid Key length: expected %d characters, got %d", KeyLength, len(k))
}
key := string(k)
s1 := key[0:7]
s2 := key[8:15]
s3 := key[16:23]
s4 := key[24:31]
n1 := decode(s1)
n2 := decode(s2)
n3 := decode(s3)
n4 := decode(s4)
n2a := n2[0:4]
n2b := n2[4:8]
n3a := n3[0:4]
n3b := n3[4:8]
return (n1 + "-" + n2a + "-" + n2b + "-" + n3a + "-" + n3b + n4), nil
}
大きな叫び声 リチャードルヘイン/crock32 crockfordのbase32操作のエンコードとデコードを確実に実装します。
このパッケージは、公式 UUID 仕様 (RFC 4122) に従う任意の UUID で動作するように設計されていますが、特に 2 つの最も人気のある UUID Go ジェネレーターとの互換性をテストし、維持しています。6
インストールは簡単です。
go get github.com/agentstation/uuidkey
基本的な使い方:
key, _ := uuidkey.Encode("d1756360-5da0-40df-9926-a76abff5601d")
fmt.Println(key)
私たちはオーバーヘッドを最小限に抑えるよう努力してきました。
BenchmarkValidate-12 33527211 35.72 ns/op
BenchmarkParse-12 32329798 36.96 ns/op
BenchmarkEncode-12 3151844 377.0 ns/op
BenchmarkDecode-12 5587066 216.7 ns/op
パフォーマンス ベンチマークを選択します。実際の走行距離は異なる場合があります。
貢献 uuidkey
私たちはメンテナンスに全力で取り組んでいます uuidkey 本番環境で使用しているため、信頼できるオープンソース ツールとして – 貢献を歓迎します。
役立つと思われる場合、または改善のアイデアがある場合は、ぜひご意見をお聞かせください。 GitHubの問題 または Discordコミュニティ。
🎨 先行技術 & 🗿 巨人の肩
プロジェクトを公開した後、同様の実装を備えたプロジェクトが他にもいくつか見つかりましたが、それでも Go を使用した UUID のエンコードとデコードの基準を満たしていませんでした。
- ウイダピキー – Go ですが、UUID 入力のエンコードまたはデコードはサポートされていません
- based_uuid – Ruby、ただしパブリック ID 用
まとめ
で エージェントステーションでは、AI エージェントがブラウザを実行し、会議に参加し、コードを実行するための独自の仮想ワークステーションを取得するプラットフォームを構築しています。数千のワークステーションに拡張する場合、ソート可能でパフォーマンスの高いキーを備えることが実用的なインフラストラクチャとなります。
しかし、開発者も私たちと同じように、API キーであっても、美しい対称的なものを高く評価していると私たちは信じています。
見つけていただければ幸いです uuidkey 便利で美しい。
#美しい #API #キーの作成 #一緒に構築しましょう