回答我自己的问题,以防其他人需要这个。我也写了一篇关于这个的文章,希望有人觉得它有用。
https://tmarkovski.github.io/eth-azure/keyvault-part1/
最初,我生成了不正确的密钥类型。我能够通过连接来自 JWK 的 X 和 Y 数组来生成密钥。这是我在 F# 中使用的示例代码。它使用 BouncyCastle 作为 Keccak 哈希函数。需要注意的重要一点是“EC-HSM”密钥类型的使用。这是 Key Vault 高级 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