/// <inheritdoc/>
        public async Task <(DidExchangeResponseMessage, ConnectionRecord)> CreateResponseAsync(IAgentContext agentContext, ConnectionRecord connectionRecord)
        {
            await connectionRecord.TriggerAsync(ConnectionTrigger.Response);

            var myDid = await Did.CreateAndStoreMyDidAsync(agentContext.Wallet, "{}");

            connectionRecord.MyDid = DidUtils.ConvertVerkeyToDidKey(myDid.VerKey);
            connectionRecord.MyVk  = myDid.VerKey;

            var provisioningRecord = await _provisioningService.GetProvisioningAsync(agentContext.Wallet);

            var didDoc = new AttachmentContent
            {
                Base64 = connectionRecord.MyDidDoc(provisioningRecord).ToJson().ToBase64Url()
            };
            await didDoc.SignWithJsonWebSignature(agentContext.Wallet, myDid.VerKey);

            var attachment = new Attachment
            {
                Id       = Guid.NewGuid().ToString(),
                MimeType = "application/json",
                Data     = didDoc
            };

            var response = new DidExchangeResponseMessage
            {
                Id     = Guid.NewGuid().ToString(),
                Did    = connectionRecord.MyDid,
                DidDoc = attachment
            };
            await _recordService.UpdateAsync(agentContext.Wallet, connectionRecord);

            return(response, connectionRecord);
        }
Ejemplo n.º 2
0
 public void CanDetectDidKey()
 {
     Assert.True(DidUtils.IsDidKey(VALID_DID_KEY));
     Assert.True(DidUtils.IsDidKey(VALID_SECP256K1_0));
     Assert.False(DidUtils.IsDidKey(VALID_FULL_VERKEY));
     Assert.False(DidUtils.IsDidKey(""));
 }
Ejemplo n.º 3
0
 public void CanDetectFullVerkey()
 {
     Assert.True(DidUtils.IsFullVerkey(VALID_FULL_VERKEY));         //Valid full verkey
     Assert.True(DidUtils.IsFullVerkey(ANOTHER_VALID_FULL_VERKEY)); // Indy seems to generate verkeys with less than 256bit (only 43 chars)
     Assert.False(DidUtils.IsFullVerkey(""));
     Assert.False(DidUtils.IsFullVerkey(VALID_ABBREVIATED_VERKEY)); //Valid abbreviated verkey
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Get a service decorator representation for this provisioning record
 /// </summary>
 /// <param name="record"></param>
 /// <param name="useDidKeyFormat"></param>
 /// <returns></returns>
 public static ServiceDecorator ToServiceDecorator(this ProvisioningRecord record, bool useDidKeyFormat = false)
 {
     return(new ServiceDecorator
     {
         ServiceEndpoint = record.Endpoint.Uri,
         RoutingKeys = useDidKeyFormat ? record.Endpoint.Verkey.Select(DidUtils.ConvertVerkeyToDidKey) : record.Endpoint.Verkey,
         RecipientKeys = new [] { useDidKeyFormat?DidUtils.ConvertVerkeyToDidKey(record.IssuerVerkey) : record.IssuerVerkey }
     });
 }
Ejemplo n.º 5
0
        /// <inheritdoc />
        public virtual async Task RegisterNymAsync(IAgentContext context, string submitterDid, string theirDid,
                                                   string theirVerkey, string role, TransactionCost paymentInfo = null)
        {
            if (DidUtils.IsFullVerkey(theirVerkey))
            {
                theirVerkey = await Did.AbbreviateVerkeyAsync(theirDid, theirVerkey);
            }

            var req = await IndyLedger.BuildNymRequestAsync(submitterDid, theirDid, theirVerkey, null, role);

            var res = await SignAndSubmitAsync(context, submitterDid, req, paymentInfo);
        }
        /// <inheritdoc />
        public virtual async Task RegisterNymAsync(Wallet wallet, Pool pool, string submitterDid, string theirDid,
                                                   string theirVerkey, string role)
        {
            if (DidUtils.IsFullVerkey(theirVerkey))
            {
                theirVerkey = await Did.AbbreviateVerkeyAsync(theirDid, theirVerkey);
            }

            var req = await Ledger.BuildNymRequestAsync(submitterDid, theirDid, theirVerkey, null, role);

            var res = await Ledger.SignAndSubmitRequestAsync(pool, wallet, submitterDid, req);

            EnsureSuccessResponse(res);
        }
        public async Task CanCreateInvitationWithDidKeyFormatAsync()
        {
            var connectionId = Guid.NewGuid().ToString();

            var(msg, record) = await _connectionService.CreateInvitationAsync(_issuerWallet,
                                                                              new InviteConfiguration { ConnectionId = connectionId, UseDidKeyFormat = true });

            var connection = await _connectionService.GetAsync(_issuerWallet, connectionId);

            Assert.True(DidUtils.IsDidKey(msg.RecipientKeys.First()));
            Assert.True(DidUtils.IsDidKey(msg.RoutingKeys.First()));
            Assert.False(connection.MultiPartyInvitation);
            Assert.Equal(ConnectionState.Invited, connection.State);
            Assert.Equal(connectionId, connection.Id);
        }
        /// <inheritdoc/>
        public async Task <(DidExchangeRequestMessage, ConnectionRecord)> CreateRequestAsync(IAgentContext agentContext, string did)
        {
            var key = await Did.KeyForDidAsync(await agentContext.Pool, agentContext.Wallet, did);

            var endpointResult = await _ledgerService.LookupServiceEndpointAsync(agentContext, did);

            var myDid = await Did.CreateAndStoreMyDidAsync(agentContext.Wallet, "{}");

            var connection = new ConnectionRecord
            {
                Endpoint = new AgentEndpoint {
                    Uri = endpointResult.Result.Endpoint
                },
                MyDid    = DidUtils.ConvertVerkeyToDidKey(myDid.VerKey),
                MyVk     = myDid.VerKey,
                TheirDid = did,
                TheirVk  = key,
                State    = ConnectionState.Negotiating,
            };
            await _recordService.AddAsync(agentContext.Wallet, connection);

            var provisioningRecord = await _provisioningService.GetProvisioningAsync(agentContext.Wallet);

            var didDoc = new AttachmentContent
            {
                Base64 = connection.MyDidDoc(provisioningRecord).ToJson().ToBase64Url()
            };
            await didDoc.SignWithJsonWebSignature(agentContext.Wallet, myDid.VerKey);

            var attachment = new Attachment
            {
                Id       = Guid.NewGuid().ToString(),
                MimeType = "application/json",
                Data     = didDoc
            };

            var request = new DidExchangeRequestMessage
            {
                Did    = connection.MyDid,
                Label  = provisioningRecord.Owner.Name,
                DidDoc = attachment
            };

            return(request, connection);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Verify the json web signature of an attachment
        /// </summary>
        /// <param name="content">The attachment content to be verified.</param>
        /// <returns>True - signature is valid; False - signature is missing or invalid.</returns>
        public static async Task <bool> VerifyJsonWebSignature(this AttachmentContent content)
        {
            try
            {
                var did = content.JsonWebSignature.Header.Kid;

                var verkey = DidUtils.ConvertDidKeyToVerkey(did);

                var message = $"{content.JsonWebSignature.Protected}.{content.Base64}";

                return(await Crypto.VerifyAsync(verkey, Encoding.ASCII.GetBytes(message),
                                                content.JsonWebSignature.Signature.GetBytesFromBase64()));
            }
            catch (Exception)
            {
                return(false);
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Sign attachment content using json web signature
        /// </summary>
        /// <param name="content">The attachment content to be signed.</param>
        /// <param name="wallet">The wallet.</param>
        /// <param name="verkey">The verkey to be used for the signing.</param>
        /// <exception cref="NullReferenceException">Throws if payload is null.</exception>
        public static async Task SignWithJsonWebSignature(this AttachmentContent content, Wallet wallet, string verkey)
        {
            var payload = content.Base64;

            if (payload == null)
            {
                throw new NullReferenceException("No data to sign");
            }

            var did = DidUtils.ConvertVerkeyToDidKey(verkey);

            var protectedHeader = new
            {
                alg = "EdDSA",
                kid = did,
                jwk = new
                {
                    kty = "OKP",
                    crv = "Ed25519",
                    x   = Multibase.Base58.Decode(verkey).ToBase64UrlString(),
                    kid = did
                }
            }.ToJson().ToBase64Url();

            var message = $"{protectedHeader}.{payload}";

            var signature = (await Crypto.SignAsync(wallet, verkey, Encoding.ASCII.GetBytes(message))).ToBase64UrlString();

            content.JsonWebSignature = new JsonWebSignature
            {
                Header = new JsonWebSignatureHeader {
                    Kid = did
                },
                Protected = protectedHeader,
                Signature = signature
            };
        }
        /// <inheritdoc />
        public virtual async Task <(ConnectionInvitationMessage, ConnectionRecord)> CreateInvitationAsync(IAgentContext agentContext,
                                                                                                          InviteConfiguration config = null)
        {
            config = config ?? new InviteConfiguration();
            var connection = new ConnectionRecord {
                Role = ConnectionRole.Inviter
            };

            connection.Id = config.ConnectionId ?? connection.Id;

            Logger.LogInformation(LoggingEvents.CreateInvitation, "ConnectionId {0}", connection.Id);

            var connectionKey = await Crypto.CreateKeyAsync(agentContext.Wallet, "{}");

            connection.SetTag(TagConstants.ConnectionKey, connectionKey);

            if (config.AutoAcceptConnection)
            {
                connection.SetTag(TagConstants.AutoAcceptConnection, "true");
            }

            connection.MultiPartyInvitation = config.MultiPartyInvitation;

            if (!config.MultiPartyInvitation)
            {
                connection.Alias = config.TheirAlias;
                if (!string.IsNullOrEmpty(config.TheirAlias.Name))
                {
                    connection.SetTag(TagConstants.Alias, config.TheirAlias.Name);
                }
            }

            foreach (var tag in config.Tags)
            {
                connection.SetTag(tag.Key, tag.Value);
            }

            var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet);

            if (string.IsNullOrEmpty(provisioning.Endpoint.Uri))
            {
                throw new AriesFrameworkException(ErrorCode.RecordInInvalidState, "Provision record has no endpoint information specified");
            }

            await RecordService.AddAsync(agentContext.Wallet, connection);

            IList <string> routingKeys = null;

            if (provisioning.Endpoint.Verkey != null)
            {
                routingKeys = (config.UseDidKeyFormat
                    ? provisioning.Endpoint.Verkey
                               .Where(DidUtils.IsFullVerkey)
                               .Select(DidUtils.ConvertVerkeyToDidKey)
                    : provisioning.Endpoint.Verkey).ToList();
            }
            string recipientKey = config.UseDidKeyFormat ? DidUtils.ConvertVerkeyToDidKey(connectionKey) : connectionKey;

            return(new ConnectionInvitationMessage(agentContext.UseMessageTypesHttps)
            {
                ServiceEndpoint = provisioning.Endpoint.Uri,
                RoutingKeys = routingKeys,
                RecipientKeys = new[] { recipientKey },
                Label = config.MyAlias.Name ?? provisioning.Owner.Name,
                ImageUrl = config.MyAlias.ImageUrl ?? provisioning.Owner.ImageUrl
            }, connection);
        }
Ejemplo n.º 12
0
 public void CanDetectVerkey()
 {
     Assert.True(DidUtils.IsVerkey(VALID_FULL_VERKEY));
     Assert.True(DidUtils.IsVerkey(VALID_ABBREVIATED_VERKEY));
     Assert.False(DidUtils.IsVerkey(""));
 }
Ejemplo n.º 13
0
 public void CanDetectFullVerkey()
 {
     Assert.True(DidUtils.IsFullVerkey(VALID_FULL_VERKEY));         //Valid full verkey
     Assert.False(DidUtils.IsFullVerkey(""));
     Assert.False(DidUtils.IsFullVerkey(VALID_ABBREVIATED_VERKEY)); //Valid abbreviated verkey
 }
        /// <inheritdoc/>
        public async Task <ConnectionRecord> ProcessRequestAsync(IAgentContext agentContext, DidExchangeRequestMessage requestMessage)
        {
            var myDid = await Did.CreateAndStoreMyDidAsync(agentContext.Wallet, "{}");

            DidDoc didDoc = null;

            if (requestMessage.DidDoc.Data.Base64 is { } data)
            {
                var isValidSignature = await requestMessage.DidDoc.Data.VerifyJsonWebSignature();

                if (isValidSignature == false)
                {
                    throw new AriesFrameworkException(ErrorCode.InvalidSignatureEncoding,
                                                      "The given JSON web signature is invalid");
                }

                var json = data.FromBase64Url();
                didDoc = json.ToObject <DidDoc>();
            }

            // Todo: Handle resolvable Dids
            if (didDoc == null)
            {
                throw new NotImplementedException("Request message must provide an attached did document");
            }

            if (didDoc.Keys.All(key => key.Type == DidDocExtensions.DefaultKeyType) == false)
            {
                throw new NotImplementedException($"Only {DidDocExtensions.DefaultKeyType} is supported");
            }

            var indyService = (IndyAgentDidDocService)didDoc.Services.First(service => service is IndyAgentDidDocService);

            var agentEndpoint = new AgentEndpoint(indyService.ServiceEndpoint, null, indyService.RoutingKeys.ToArray());

            var connectionRecord = new ConnectionRecord
            {
                Id    = Guid.NewGuid().ToString(),
                Alias = new ConnectionAlias {
                    Name = requestMessage.Label
                },
                MyDid    = DidUtils.ConvertVerkeyToDidKey(myDid.VerKey),
                MyVk     = myDid.VerKey,
                TheirDid = requestMessage.Did,
                TheirVk  = didDoc.Keys.FirstOrDefault(key => key.Controller == requestMessage.Did)?.PublicKeyBase58
                           ?? throw new NullReferenceException("Missing public for controller"),
                                 Endpoint = agentEndpoint,
                                 State    = ConnectionState.Negotiating
            };
            await _recordService.AddAsync(agentContext.Wallet, connectionRecord);

            _eventAggregator.Publish(
                new ServiceMessageProcessingEvent
            {
                MessageType = requestMessage.Type,
                RecordId    = connectionRecord.Id,
                ThreadId    = requestMessage.GetThreadId()
            });

            return(connectionRecord);
        }
Ejemplo n.º 15
0
 public void ConvertNonEd25519KeysToDidKeyWillThrowArgumentException()
 {
     Assert.Throws <ArgumentException>(() => DidUtils.ConvertDidKeyToVerkey(VALID_SECP256K1_0));
 }
Ejemplo n.º 16
0
        public void CanConvertVerkeyToDidKey()
        {
            var result = DidUtils.ConvertVerkeyToDidKey(ORIG_VERKEY);

            Assert.Equal(DERIVED_DID_KEY, result);
        }