从Json Web Key

时间:2018-01-25 16:17:18

标签: .net ethereum public-key azure-keyvault jwk

我有一个包含公钥信息的Json Web Key,我想将公钥作为字节数组。我的目标是最终使用Keccak哈希从中获取以太坊地址。我理解从公钥字节数组中获取地址的过程,但我不知道如何获取这个字节数组。我的方案是,使用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环境中运行。如何获取公钥的字节数组? 谢谢

1 个答案:

答案 0 :(得分:0)

回答我自己的问题以防其他人需要这个问题。 我还写了一篇关于此的文章,希望有人觉得它很有用。

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
相关问题