/// <summary> /// Create a key ID for the key. /// </summary> /// <param name="key"></param> /// <returns></returns> /// <remarks> /// The key id is the SHA-256 multihash of its public key. The public key is /// a protobuf encoding containing a type and /// the DER encoding of the PKCS SubjectPublicKeyInfo. /// </remarks> MultiHash CreateKeyId(AsymmetricKeyParameter key) { var spki = SubjectPublicKeyInfoFactory .CreateSubjectPublicKeyInfo(key) .GetDerEncoded(); // Add protobuf cruft. var publicKey = new Proto.PublicKey { Data = spki }; if (key is RsaKeyParameters) { publicKey.Type = Proto.KeyType.RSA; } else if (key is ECPublicKeyParameters) { publicKey.Type = Proto.KeyType.Secp256k1; } else { throw new NotSupportedException($"The key type {key.GetType().Name} is not supported."); } using (var ms = new MemoryStream()) { ProtoBuf.Serializer.Serialize(ms, publicKey); ms.Position = 0; return(MultiHash.ComputeHash(ms, "sha2-256")); } }
/// <summary> /// Gets the IPFS encoded public key for the specified key. /// </summary> /// <param name="name"> /// The local name of the key. /// </param> /// <param name="cancel"> /// Is used to stop the task. When cancelled, the <see cref="TaskCanceledException"/> is raised. /// </param> /// <returns> /// A task that represents the asynchronous operation. The task's result is /// the IPFS encoded public key. /// </returns> /// <remarks> /// The IPFS public key is the base-64 encoding of a protobuf encoding containing /// a type and the DER encoding of the PKCS Subject Public Key Info. /// </remarks> /// <seealso href="https://tools.ietf.org/html/rfc5280#section-4.1.2.7"/> public async Task <string> GetPublicKeyAsync(string name, CancellationToken cancel = default(CancellationToken)) { string result = null; using (var repo = await ipfs.Repository(cancel)) { var ekey = await repo.EncryptedKeys .Where(k => k.Name == name) .FirstOrDefaultAsync(cancel); if (ekey != null) { UseEncryptedKey(ekey, key => { var kp = GetKeyPairFromPrivateKey(key); var spki = SubjectPublicKeyInfoFactory .CreateSubjectPublicKeyInfo(kp.Public) .GetDerEncoded(); // Add protobuf cruft. var publicKey = new Proto.PublicKey { Data = spki }; if (kp.Public is RsaKeyParameters) { publicKey.Type = Proto.KeyType.RSA; } else if (kp.Public is ECPublicKeyParameters) { publicKey.Type = Proto.KeyType.Secp256k1; } else { throw new NotSupportedException($"The key type {kp.Public.GetType().Name} is not supported."); } using (var ms = new MemoryStream()) { ProtoBuf.Serializer.Serialize(ms, publicKey); result = Convert.ToBase64String(ms.ToArray()); } }); } } return(result); }
/// <summary> /// Gets the IPFS encoded public key for the specified key. /// </summary> /// <param name="name"> /// The local name of the key. /// </param> /// <param name="cancel"> /// Is used to stop the task. When cancelled, the <see cref="TaskCanceledException"/> is raised. /// </param> /// <returns> /// A task that represents the asynchronous operation. The task's result is /// the IPFS encoded public key. /// </returns> /// <remarks> /// The IPFS public key is the base-64 encoding of a protobuf encoding containing /// a type and the DER encoding of the PKCS Subject Public Key Info. /// </remarks> /// <seealso href="https://tools.ietf.org/html/rfc5280#section-4.1.2.7"/> public async Task <string> GetPublicKeyAsync(string name, CancellationToken cancel = default(CancellationToken)) { // TODO: Rename to GetIpfsPublicKeyAsync string result = null; var ekey = await Store.TryGetAsync(name, cancel).ConfigureAwait(false); if (ekey != null) { UseEncryptedKey(ekey, key => { var kp = GetKeyPairFromPrivateKey(key); var spki = SubjectPublicKeyInfoFactory .CreateSubjectPublicKeyInfo(kp.Public) .GetDerEncoded(); // Add protobuf cruft. var publicKey = new Proto.PublicKey { Data = spki }; if (kp.Public is RsaKeyParameters) { publicKey.Type = Proto.KeyType.RSA; } else if (kp.Public is Ed25519PublicKeyParameters) { publicKey.Type = Proto.KeyType.Ed25519; } else if (kp.Public is ECPublicKeyParameters) { publicKey.Type = Proto.KeyType.Secp256k1; } else { throw new NotSupportedException($"The key type {kp.Public.GetType().Name} is not supported."); } using (var ms = new MemoryStream()) { ProtoBuf.Serializer.Serialize(ms, publicKey); result = Convert.ToBase64String(ms.ToArray()); } }); } return(result); }
/// <summary> /// Create a key ID for the key. /// </summary> /// <param name="key"></param> /// <returns></returns> /// <remarks> /// The key id is the SHA-256 multihash of its public key. The public key is /// a protobuf encoding containing a type and /// the DER encoding of the PKCS SubjectPublicKeyInfo. /// </remarks> MultiHash CreateKeyId(AsymmetricKeyParameter key) { var spki = SubjectPublicKeyInfoFactory .CreateSubjectPublicKeyInfo(key) .GetDerEncoded(); // Add protobuf cruft. var publicKey = new Proto.PublicKey { Data = spki }; if (key is RsaKeyParameters) { publicKey.Type = Proto.KeyType.RSA; } else if (key is ECPublicKeyParameters) { publicKey.Type = Proto.KeyType.Secp256k1; } else if (key is Ed25519PublicKeyParameters) { publicKey.Type = Proto.KeyType.Ed25519; } else { throw new NotSupportedException($"The key type {key.GetType().Name} is not supported."); } using (var ms = new MemoryStream()) { ProtoBuf.Serializer.Serialize(ms, publicKey); // If the length of the serialized bytes <= 42, then we compute the "identity" multihash of // the serialized bytes. The idea here is that if the serialized byte array // is short enough, we can fit it in a multihash verbatim without having to // condense it using a hash function. var alg = (ms.Length <= 48) ? "identity" : "sha2-256"; ms.Position = 0; return(MultiHash.ComputeHash(ms, alg)); } }