从 Json Web Key 获取 public key 字节数组
Obtain public key byte array from Json Web Key
我有一个包含 public 密钥信息的 Json Web 密钥,我想获取字节数组形式的 public 密钥。我的目标是最终使用 Keccak 哈希从中导出以太坊地址。从public键字节数组中获取地址的过程我明白了,但是我不知道如何获取这个字节数组。我的方案是,使用 Azure Key Vault API 生成 EC 密钥,检索密钥(JWK 格式),然后找到地址。 JWK 具有以下格式。
{
"kid": "https: //mykeyvault.vault.azure.net/keys/testeckey/8bad08aaae514efe981eaab4e590778d",
"kty": "EC",
"key_ops": [
"sign",
"verify"
],
"crv": "P-256",
"x": "YooqHyo7hlmcrBs5lDSSUsB0axzvorjxzNl6DBZLUf0",
"y": "NM-JrV6NTbUgILY_sBm5VgYxt1zYccCOCFtSDicSfWM"
}
我正在使用 Azure .NET SDK,我可以选择使用 Bouncy Castle for .NET 或任何 JS 库,因为项目也可以 运行 在 Node.js 环境中。如何获取 public 键的字节数组?
谢谢
回答我自己的问题以防其他人需要这个。
我也写了一篇关于这个的文章,希望有人觉得它有用。
https://tmarkovski.github.io/eth-azure/keyvault-part1/
最初,我生成的密钥类型不正确。我能够通过连接来自 JWK 的 X 和 Y 数组来生成密钥。这是我在 F# 中使用的示例代码。它使用 BouncyCastle 作为 Keccak 哈希函数。
需要注意的重要一点是 "EC-HSM" 键类型的使用。这是 Key Vault 的 Premium SKU 的一部分,只有这种类型支持 SECP256K1 曲线,否则如果使用 "EC" 密钥类型会引发异常。
open Microsoft.Azure.KeyVault
open System.Threading.Tasks
open System
open Microsoft.IdentityModel.Clients.ActiveDirectory
open Microsoft.Azure.KeyVault.Models
open Microsoft.Azure.KeyVault.WebKey
open Org.BouncyCastle.Crypto.Digests
open Org.BouncyCastle.Crypto
/// Implements an extension method that overloads the standard
/// 'Bind' of the 'async' builder. The new overload awaits on
/// a standard .NET task
type AsyncBuilder with
member __.Bind(t:Task<'T>, f:'T -> Async<'R>) : Async<'R> =
async.Bind(Async.AwaitTask t, f)
let vaultUri = "https://__mykeyvault__.vault.azure.net/"
let clientId = "..."
let clientSecret = "..."
type AuthenticationCallback = KeyVaultClient.AuthenticationCallback
let getAccessToken (authority:string) (resource:string) (scope:string) =
let clientCredential = new ClientCredential(clientId, clientSecret)
let context = new AuthenticationContext(authority, TokenCache.DefaultShared)
async {
let! result = context.AcquireTokenAsync(resource, clientCredential)
return result.AccessToken;
} |> Async.StartAsTask
let client = new KeyVaultClient(new KeyVaultCredential(new AuthenticationCallback(getAccessToken)))
let createKey name =
let keyParams = new NewKeyParameters()
keyParams.Kty <- "EC-HSM"
keyParams.CurveName <- EcKey.SECP256K1
async {
let! result = client.CreateKeyAsync(vaultUri, name, keyParams)
return result
} |> Async.RunSynchronously
let getKey name =
async {
let! result = client.GetKeyAsync(vaultBaseUrl = vaultUri, keyName = name)
return result
} |> Async.RunSynchronously
let getPubKey (jwk:KeyBundle) =
Array.concat [| jwk.Key.X; jwk.Key.Y |]
let hash (digest:IDigest) data =
digest.Reset()
digest.BlockUpdate(data, 0, data.Length)
let a = digest.GetDigestSize() |> Array.zeroCreate
digest.DoFinal(a, 0) |> ignore
a
let toHex (x:byte) = x.ToString("x2")
let getAddress pubKey =
pubKey
|> hash (new KeccakDigest(256))
|> Array.map toHex
|> Array.skip 12
|> String.Concat
|> (+) "0x"
createKey "testEcKey"
|> getPubKey
|> getAddress
|> Console.WriteLine
// 0x51e4370152c132d307c302d8146c63ca6bf41167
我有一个包含 public 密钥信息的 Json Web 密钥,我想获取字节数组形式的 public 密钥。我的目标是最终使用 Keccak 哈希从中导出以太坊地址。从public键字节数组中获取地址的过程我明白了,但是我不知道如何获取这个字节数组。我的方案是,使用 Azure Key Vault API 生成 EC 密钥,检索密钥(JWK 格式),然后找到地址。 JWK 具有以下格式。
{
"kid": "https: //mykeyvault.vault.azure.net/keys/testeckey/8bad08aaae514efe981eaab4e590778d",
"kty": "EC",
"key_ops": [
"sign",
"verify"
],
"crv": "P-256",
"x": "YooqHyo7hlmcrBs5lDSSUsB0axzvorjxzNl6DBZLUf0",
"y": "NM-JrV6NTbUgILY_sBm5VgYxt1zYccCOCFtSDicSfWM"
}
我正在使用 Azure .NET SDK,我可以选择使用 Bouncy Castle for .NET 或任何 JS 库,因为项目也可以 运行 在 Node.js 环境中。如何获取 public 键的字节数组? 谢谢
回答我自己的问题以防其他人需要这个。 我也写了一篇关于这个的文章,希望有人觉得它有用。
https://tmarkovski.github.io/eth-azure/keyvault-part1/
最初,我生成的密钥类型不正确。我能够通过连接来自 JWK 的 X 和 Y 数组来生成密钥。这是我在 F# 中使用的示例代码。它使用 BouncyCastle 作为 Keccak 哈希函数。 需要注意的重要一点是 "EC-HSM" 键类型的使用。这是 Key Vault 的 Premium SKU 的一部分,只有这种类型支持 SECP256K1 曲线,否则如果使用 "EC" 密钥类型会引发异常。
open Microsoft.Azure.KeyVault
open System.Threading.Tasks
open System
open Microsoft.IdentityModel.Clients.ActiveDirectory
open Microsoft.Azure.KeyVault.Models
open Microsoft.Azure.KeyVault.WebKey
open Org.BouncyCastle.Crypto.Digests
open Org.BouncyCastle.Crypto
/// Implements an extension method that overloads the standard
/// 'Bind' of the 'async' builder. The new overload awaits on
/// a standard .NET task
type AsyncBuilder with
member __.Bind(t:Task<'T>, f:'T -> Async<'R>) : Async<'R> =
async.Bind(Async.AwaitTask t, f)
let vaultUri = "https://__mykeyvault__.vault.azure.net/"
let clientId = "..."
let clientSecret = "..."
type AuthenticationCallback = KeyVaultClient.AuthenticationCallback
let getAccessToken (authority:string) (resource:string) (scope:string) =
let clientCredential = new ClientCredential(clientId, clientSecret)
let context = new AuthenticationContext(authority, TokenCache.DefaultShared)
async {
let! result = context.AcquireTokenAsync(resource, clientCredential)
return result.AccessToken;
} |> Async.StartAsTask
let client = new KeyVaultClient(new KeyVaultCredential(new AuthenticationCallback(getAccessToken)))
let createKey name =
let keyParams = new NewKeyParameters()
keyParams.Kty <- "EC-HSM"
keyParams.CurveName <- EcKey.SECP256K1
async {
let! result = client.CreateKeyAsync(vaultUri, name, keyParams)
return result
} |> Async.RunSynchronously
let getKey name =
async {
let! result = client.GetKeyAsync(vaultBaseUrl = vaultUri, keyName = name)
return result
} |> Async.RunSynchronously
let getPubKey (jwk:KeyBundle) =
Array.concat [| jwk.Key.X; jwk.Key.Y |]
let hash (digest:IDigest) data =
digest.Reset()
digest.BlockUpdate(data, 0, data.Length)
let a = digest.GetDigestSize() |> Array.zeroCreate
digest.DoFinal(a, 0) |> ignore
a
let toHex (x:byte) = x.ToString("x2")
let getAddress pubKey =
pubKey
|> hash (new KeccakDigest(256))
|> Array.map toHex
|> Array.skip 12
|> String.Concat
|> (+) "0x"
createKey "testEcKey"
|> getPubKey
|> getAddress
|> Console.WriteLine
// 0x51e4370152c132d307c302d8146c63ca6bf41167