github.com/hyperledger/aries-framework-go@v0.3.2/pkg/didcomm/protocol/didexchange/states_test.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package didexchange 8 9 import ( 10 "encoding/base64" 11 "encoding/json" 12 "errors" 13 "fmt" 14 "testing" 15 "time" 16 17 "github.com/google/uuid" 18 "github.com/stretchr/testify/require" 19 20 "github.com/hyperledger/aries-framework-go/component/storageutil/mem" 21 commonmodel "github.com/hyperledger/aries-framework-go/pkg/common/model" 22 "github.com/hyperledger/aries-framework-go/pkg/crypto/tinkcrypto" 23 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/model" 24 "github.com/hyperledger/aries-framework-go/pkg/didcomm/common/service" 25 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/decorator" 26 "github.com/hyperledger/aries-framework-go/pkg/didcomm/protocol/mediator" 27 "github.com/hyperledger/aries-framework-go/pkg/didcomm/transport" 28 diddoc "github.com/hyperledger/aries-framework-go/pkg/doc/did" 29 vdrapi "github.com/hyperledger/aries-framework-go/pkg/framework/aries/api/vdr" 30 "github.com/hyperledger/aries-framework-go/pkg/kms" 31 mockcrypto "github.com/hyperledger/aries-framework-go/pkg/mock/crypto" 32 mockdispatcher "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/dispatcher" 33 "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol" 34 mockroute "github.com/hyperledger/aries-framework-go/pkg/mock/didcomm/protocol/mediator" 35 mockdiddoc "github.com/hyperledger/aries-framework-go/pkg/mock/diddoc" 36 mockkms "github.com/hyperledger/aries-framework-go/pkg/mock/kms" 37 mockstorage "github.com/hyperledger/aries-framework-go/pkg/mock/storage" 38 mockvdr "github.com/hyperledger/aries-framework-go/pkg/mock/vdr" 39 "github.com/hyperledger/aries-framework-go/pkg/store/connection" 40 didstore "github.com/hyperledger/aries-framework-go/pkg/store/did" 41 "github.com/hyperledger/aries-framework-go/pkg/vdr/fingerprint" 42 ) 43 44 func TestNoopState(t *testing.T) { 45 noop := &noOp{} 46 require.Equal(t, "noop", noop.Name()) 47 48 t.Run("must not transition to any state", func(t *testing.T) { 49 all := []state{&null{}, &invited{}, &requested{}, &responded{}, &completed{}} 50 for _, s := range all { 51 require.False(t, noop.CanTransitionTo(s)) 52 } 53 }) 54 } 55 56 // null state can transition to invited state or requested state. 57 func TestNullState(t *testing.T) { 58 nul := &null{} 59 require.Equal(t, "null", nul.Name()) 60 require.False(t, nul.CanTransitionTo(nul)) 61 require.True(t, nul.CanTransitionTo(&invited{})) 62 require.True(t, nul.CanTransitionTo(&requested{})) 63 require.False(t, nul.CanTransitionTo(&responded{})) 64 require.False(t, nul.CanTransitionTo(&completed{})) 65 } 66 67 // invited can only transition to requested state. 68 func TestInvitedState(t *testing.T) { 69 inv := &invited{} 70 require.Equal(t, "invited", inv.Name()) 71 require.False(t, inv.CanTransitionTo(&null{})) 72 require.False(t, inv.CanTransitionTo(inv)) 73 require.True(t, inv.CanTransitionTo(&requested{})) 74 require.False(t, inv.CanTransitionTo(&responded{})) 75 require.False(t, inv.CanTransitionTo(&completed{})) 76 } 77 78 // requested can only transition to responded state. 79 func TestRequestedState(t *testing.T) { 80 req := &requested{} 81 require.Equal(t, "requested", req.Name()) 82 require.False(t, req.CanTransitionTo(&null{})) 83 require.False(t, req.CanTransitionTo(&invited{})) 84 require.False(t, req.CanTransitionTo(req)) 85 require.True(t, req.CanTransitionTo(&responded{})) 86 require.False(t, req.CanTransitionTo(&completed{})) 87 } 88 89 // responded can only transition to completed state. 90 func TestRespondedState(t *testing.T) { 91 res := &responded{} 92 require.Equal(t, "responded", res.Name()) 93 require.False(t, res.CanTransitionTo(&null{})) 94 require.False(t, res.CanTransitionTo(&invited{})) 95 require.False(t, res.CanTransitionTo(&requested{})) 96 require.False(t, res.CanTransitionTo(res)) 97 require.True(t, res.CanTransitionTo(&completed{})) 98 } 99 100 // completed is an end state. 101 func TestCompletedState(t *testing.T) { 102 comp := &completed{} 103 require.Equal(t, "completed", comp.Name()) 104 require.False(t, comp.CanTransitionTo(&null{})) 105 require.False(t, comp.CanTransitionTo(&invited{})) 106 require.False(t, comp.CanTransitionTo(&requested{})) 107 require.False(t, comp.CanTransitionTo(&responded{})) 108 require.False(t, comp.CanTransitionTo(&abandoned{})) 109 require.False(t, comp.CanTransitionTo(comp)) 110 } 111 112 func TestAbandonedState(t *testing.T) { 113 ab := &abandoned{} 114 require.Equal(t, StateIDAbandoned, ab.Name()) 115 require.False(t, ab.CanTransitionTo(&null{})) 116 require.False(t, ab.CanTransitionTo(&invited{})) 117 require.False(t, ab.CanTransitionTo(&requested{})) 118 require.False(t, ab.CanTransitionTo(&responded{})) 119 require.False(t, ab.CanTransitionTo(&completed{})) 120 connRec, _, _, err := ab.ExecuteInbound(&stateMachineMsg{}, "", &context{}) 121 require.Error(t, err) 122 require.Contains(t, err.Error(), "not implemented") 123 require.Nil(t, connRec) 124 } 125 126 func TestStateFromMsgType(t *testing.T) { 127 t.Run("invited", func(t *testing.T) { 128 expected := &invited{} 129 actual, err := stateFromMsgType(InvitationMsgType) 130 require.NoError(t, err) 131 require.Equal(t, expected.Name(), actual.Name()) 132 }) 133 t.Run("requested", func(t *testing.T) { 134 expected := &requested{} 135 actual, err := stateFromMsgType(RequestMsgType) 136 require.NoError(t, err) 137 require.Equal(t, expected.Name(), actual.Name()) 138 }) 139 t.Run("responded", func(t *testing.T) { 140 expected := &responded{} 141 actual, err := stateFromMsgType(ResponseMsgType) 142 require.NoError(t, err) 143 require.Equal(t, expected.Name(), actual.Name()) 144 }) 145 t.Run("completed", func(t *testing.T) { 146 expected := &completed{} 147 actual, err := stateFromMsgType(AckMsgType) 148 require.NoError(t, err) 149 require.Equal(t, expected.Name(), actual.Name()) 150 }) 151 t.Run("invalid", func(t *testing.T) { 152 actual, err := stateFromMsgType("invalid") 153 require.Nil(t, actual) 154 require.Error(t, err) 155 require.Contains(t, err.Error(), "unrecognized msgType: invalid") 156 }) 157 } 158 159 func TestStateFromName(t *testing.T) { 160 t.Run("noop", func(t *testing.T) { 161 expected := &noOp{} 162 actual, err := stateFromName(expected.Name()) 163 require.NoError(t, err) 164 require.Equal(t, expected.Name(), actual.Name()) 165 }) 166 t.Run("null", func(t *testing.T) { 167 expected := &null{} 168 actual, err := stateFromName(expected.Name()) 169 require.NoError(t, err) 170 require.Equal(t, expected.Name(), actual.Name()) 171 }) 172 t.Run("invited", func(t *testing.T) { 173 expected := &invited{} 174 actual, err := stateFromName(expected.Name()) 175 require.NoError(t, err) 176 require.Equal(t, expected.Name(), actual.Name()) 177 }) 178 t.Run("requested", func(t *testing.T) { 179 expected := &requested{} 180 actual, err := stateFromName(expected.Name()) 181 require.NoError(t, err) 182 require.Equal(t, expected.Name(), actual.Name()) 183 }) 184 t.Run("responded", func(t *testing.T) { 185 expected := &responded{} 186 actual, err := stateFromName(expected.Name()) 187 require.NoError(t, err) 188 require.Equal(t, expected.Name(), actual.Name()) 189 }) 190 t.Run("completed", func(t *testing.T) { 191 expected := &completed{} 192 actual, err := stateFromName(expected.Name()) 193 require.NoError(t, err) 194 require.Equal(t, expected.Name(), actual.Name()) 195 }) 196 t.Run("abandoned", func(t *testing.T) { 197 expected := &abandoned{} 198 actual, err := stateFromName(expected.Name()) 199 require.NoError(t, err) 200 require.Equal(t, expected.Name(), actual.Name()) 201 }) 202 t.Run("undefined", func(t *testing.T) { 203 actual, err := stateFromName("undefined") 204 require.Nil(t, actual) 205 require.Error(t, err) 206 require.Contains(t, err.Error(), "invalid state name") 207 }) 208 } 209 210 // noOp.ExecuteInbound() returns nil, error. 211 func TestNoOpState_Execute(t *testing.T) { 212 _, followup, _, err := (&noOp{}).ExecuteInbound(&stateMachineMsg{}, "", &context{}) 213 require.Error(t, err) 214 require.Contains(t, err.Error(), "cannot execute no-op") 215 require.Nil(t, followup) 216 } 217 218 // null.ExecuteInbound() is a no-op. 219 func TestNullState_Execute(t *testing.T) { 220 _, followup, _, err := (&null{}).ExecuteInbound(&stateMachineMsg{}, "", &context{}) 221 require.NoError(t, err) 222 require.IsType(t, &noOp{}, followup) 223 } 224 225 func TestInvitedState_Execute(t *testing.T) { 226 t.Run("rejects msgs other than invitations", func(t *testing.T) { 227 others := []service.DIDCommMsg{ 228 service.NewDIDCommMsgMap(Request{Type: RequestMsgType}), 229 service.NewDIDCommMsgMap(Response{Type: ResponseMsgType}), 230 service.NewDIDCommMsgMap(model.Ack{Type: AckMsgType}), 231 } 232 for _, msg := range others { 233 _, _, _, err := (&invited{}).ExecuteInbound(&stateMachineMsg{ 234 DIDCommMsg: msg, 235 }, "", &context{}) 236 require.Error(t, err) 237 require.Contains(t, err.Error(), "illegal msg type") 238 } 239 }) 240 t.Run("followup to 'requested' on inbound invitations", func(t *testing.T) { 241 invitationPayloadBytes, err := json.Marshal(&Invitation{ 242 Type: InvitationMsgType, 243 ID: randomString(), 244 Label: "Bob", 245 RecipientKeys: []string{"8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K"}, 246 ServiceEndpoint: "https://localhost:8090", 247 RoutingKeys: []string{"8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K"}, 248 }) 249 require.NoError(t, err) 250 connRec, followup, _, err := (&invited{}).ExecuteInbound( 251 &stateMachineMsg{ 252 DIDCommMsg: bytesToDIDCommMsg(t, invitationPayloadBytes), 253 connRecord: &connection.Record{}, 254 }, 255 "", 256 &context{}) 257 require.NoError(t, err) 258 require.Equal(t, &requested{}, followup) 259 require.NotNil(t, connRec) 260 }) 261 t.Run("followup to 'requested' on inbound oobinvitations", func(t *testing.T) { 262 connRec, followup, action, err := (&invited{}).ExecuteInbound( 263 &stateMachineMsg{ 264 DIDCommMsg: service.NewDIDCommMsgMap(&OOBInvitation{Type: oobMsgType}), 265 connRecord: &connection.Record{}, 266 }, 267 "", 268 &context{}, 269 ) 270 require.NoError(t, err) 271 require.Equal(t, &requested{}, followup) 272 require.NotNil(t, connRec) 273 require.NotNil(t, action) 274 }) 275 } 276 277 //nolint:gocognit,gocyclo 278 func TestRequestedState_Execute(t *testing.T) { 279 prov := getProvider(t) 280 // Alice receives an invitation from Bob 281 invitationPayloadBytes, err := json.Marshal(&Invitation{ 282 Type: InvitationMsgType, 283 ID: randomString(), 284 Label: "Bob", 285 RecipientKeys: []string{"8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K"}, 286 ServiceEndpoint: "https://localhost:8090", 287 RoutingKeys: []string{"8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K"}, 288 }) 289 require.NoError(t, err) 290 291 mtps := []string{ 292 transport.MediaTypeDIDCommV2Profile, 293 transport.MediaTypeRFC0019EncryptedEnvelope, 294 transport.MediaTypeProfileDIDCommAIP1, 295 } 296 297 for _, mtp := range mtps { 298 var didServiceType string 299 300 switch mtp { 301 case transport.MediaTypeDIDCommV2Profile, transport.MediaTypeAIP2RFC0587Profile: 302 didServiceType = vdrapi.DIDCommV2ServiceType 303 default: 304 didServiceType = vdrapi.DIDCommServiceType 305 } 306 307 t.Run("rejects messages other than invitations or requests", func(t *testing.T) { 308 others := []service.DIDCommMsg{ 309 service.NewDIDCommMsgMap(Response{Type: ResponseMsgType}), 310 service.NewDIDCommMsgMap(model.Ack{Type: AckMsgType}), 311 } 312 for _, msg := range others { 313 _, _, _, e := (&requested{}).ExecuteInbound(&stateMachineMsg{ 314 DIDCommMsg: msg, 315 }, "", &context{}) 316 require.Error(t, e) 317 require.Contains(t, e.Error(), "illegal msg type") 318 } 319 }) 320 t.Run("handle inbound invitations", func(t *testing.T) { 321 tests := []struct { 322 name string 323 ctx *context 324 }{ 325 { 326 name: "using context with ED25519 main VM and X25519 keyAgreement", 327 ctx: getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp), 328 }, 329 { 330 name: "using context with P-256 main VM and P-256 keyAgreement", 331 ctx: getContext(t, &prov, kms.ECDSAP256TypeIEEEP1363, kms.NISTP256ECDHKWType, mtp), 332 }, 333 { 334 name: "using context with P-384 main VM and P-384 keyAgreement", 335 ctx: getContext(t, &prov, kms.ECDSAP384TypeIEEEP1363, kms.NISTP384ECDHKWType, mtp), 336 }, 337 { 338 name: "using context with P-521 main VM and P-521 keyAgreement", 339 ctx: getContext(t, &prov, kms.ECDSAP521TypeIEEEP1363, kms.NISTP521ECDHKWType, mtp), 340 }, 341 { 342 name: "using context with ED25519 main VM and P-384 keyAgreement", 343 ctx: getContext(t, &prov, kms.ED25519Type, kms.NISTP384ECDHKWType, mtp), 344 }, 345 } 346 347 for _, tt := range tests { 348 tc := tt 349 t.Run(tc.name, func(t *testing.T) { 350 msg, e := service.ParseDIDCommMsgMap(invitationPayloadBytes) 351 require.NoError(t, e) 352 thid, e := msg.ThreadID() 353 require.NoError(t, e) 354 connRec, _, _, e := (&requested{}).ExecuteInbound(&stateMachineMsg{ 355 DIDCommMsg: msg, 356 connRecord: &connection.Record{}, 357 }, thid, tc.ctx) 358 require.NoError(t, e) 359 require.NotNil(t, connRec.MyDID) 360 }) 361 } 362 }) 363 t.Run("handle inbound oob invitations", func(t *testing.T) { 364 tests := []struct { 365 name string 366 ctx *context 367 }{ 368 { 369 name: "using context with ED25519 main VM and X25519 keyAgreement", 370 ctx: getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp), 371 }, 372 { 373 name: "using context with P-256 main VM and P-256 keyAgreement", 374 ctx: getContext(t, &prov, kms.ECDSAP256TypeIEEEP1363, kms.NISTP256ECDHKWType, mtp), 375 }, 376 { 377 name: "using context with P-384 main VM and P-384 keyAgreement", 378 ctx: getContext(t, &prov, kms.ECDSAP384TypeIEEEP1363, kms.NISTP384ECDHKWType, mtp), 379 }, 380 { 381 name: "using context with P-521 main VM and P-521 keyAgreement", 382 ctx: getContext(t, &prov, kms.ECDSAP521TypeIEEEP1363, kms.NISTP521ECDHKWType, mtp), 383 }, 384 { 385 name: "using context with ED25519 main VM and P-384 keyAgreement", 386 ctx: getContext(t, &prov, kms.ED25519Type, kms.NISTP384ECDHKWType, mtp), 387 }, 388 } 389 390 for _, tt := range tests { 391 tc := tt 392 t.Run(tc.name, func(t *testing.T) { 393 connRec, followup, action, e := (&requested{}).ExecuteInbound(&stateMachineMsg{ 394 DIDCommMsg: service.NewDIDCommMsgMap(&OOBInvitation{ 395 ID: uuid.New().String(), 396 Type: oobMsgType, 397 ThreadID: uuid.New().String(), 398 TheirLabel: "test", 399 Target: &diddoc.Service{ 400 ID: uuid.New().String(), 401 Type: didServiceType, 402 Priority: 0, 403 RecipientKeys: []string{"key"}, 404 ServiceEndpoint: commonmodel.NewDIDCommV1Endpoint("http://test.com"), 405 }, 406 }), 407 connRecord: &connection.Record{}, 408 }, "", tc.ctx) 409 require.NoError(t, e) 410 require.NotEmpty(t, connRec.MyDID) 411 require.Equal(t, &noOp{}, followup) 412 require.NotNil(t, action) 413 }) 414 } 415 }) 416 t.Run("handle inbound oob invitations", func(t *testing.T) { 417 tests := []struct { 418 name string 419 ctx *context 420 }{ 421 { 422 name: "using context with ED25519 main VM and X25519 keyAgreement", 423 ctx: getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp), 424 }, 425 { 426 name: "using context with P-256 main VM and P-256 keyAgreement", 427 ctx: getContext(t, &prov, kms.ECDSAP256TypeIEEEP1363, kms.NISTP256ECDHKWType, mtp), 428 }, 429 { 430 name: "using context with P-384 main VM and P-384 keyAgreement", 431 ctx: getContext(t, &prov, kms.ECDSAP384TypeIEEEP1363, kms.NISTP384ECDHKWType, mtp), 432 }, 433 { 434 name: "using context with P-521 main VM and P-521 keyAgreement", 435 ctx: getContext(t, &prov, kms.ECDSAP521TypeIEEEP1363, kms.NISTP521ECDHKWType, mtp), 436 }, 437 { 438 name: "using context with ED25519 main VM and P-384 keyAgreement", 439 ctx: getContext(t, &prov, kms.ED25519Type, kms.NISTP384ECDHKWType, mtp), 440 }, 441 } 442 443 for _, tt := range tests { 444 tc := tt 445 t.Run(tc.name, func(t *testing.T) { 446 connRec, followup, action, e := (&requested{}).ExecuteInbound(&stateMachineMsg{ 447 DIDCommMsg: service.NewDIDCommMsgMap(&OOBInvitation{ 448 ID: uuid.New().String(), 449 Type: oobMsgType, 450 ThreadID: uuid.New().String(), 451 TheirLabel: "test", 452 Target: &diddoc.Service{ 453 ID: uuid.New().String(), 454 Type: didServiceType, 455 Priority: 0, 456 RecipientKeys: []string{"key"}, 457 ServiceEndpoint: commonmodel.NewDIDCommV1Endpoint("http://test.com"), 458 }, 459 }), 460 connRecord: &connection.Record{}, 461 }, "", tc.ctx) 462 require.NoError(t, e) 463 require.NotEmpty(t, connRec.MyDID) 464 require.Equal(t, &noOp{}, followup) 465 require.NotNil(t, action) 466 }) 467 } 468 }) 469 t.Run("handle inbound oob invitations with label", func(t *testing.T) { 470 expected := "my test label" 471 dispatched := false 472 tests := []struct { 473 name string 474 ctx *context 475 }{ 476 { 477 name: "using context with ED25519 main VM and X25519 keyAgreement", 478 ctx: getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp), 479 }, 480 { 481 name: "using context with P-256 main VM and P-256 keyAgreement", 482 ctx: getContext(t, &prov, kms.ECDSAP256TypeIEEEP1363, kms.NISTP256ECDHKWType, mtp), 483 }, 484 { 485 name: "using context with P-384 main VM and P-384 keyAgreement", 486 ctx: getContext(t, &prov, kms.ECDSAP384TypeIEEEP1363, kms.NISTP384ECDHKWType, mtp), 487 }, 488 { 489 name: "using context with P-521 main VM and P-521 keyAgreement", 490 ctx: getContext(t, &prov, kms.ECDSAP521TypeIEEEP1363, kms.NISTP521ECDHKWType, mtp), 491 }, 492 { 493 name: "using context with ED25519 main VM and P-384 keyAgreement", 494 ctx: getContext(t, &prov, kms.ED25519Type, kms.NISTP384ECDHKWType, mtp), 495 }, 496 } 497 498 for _, tt := range tests { 499 tc := tt 500 t.Run(tc.name, func(t *testing.T) { 501 tc.ctx.outboundDispatcher = &mockdispatcher.MockOutbound{ 502 ValidateSend: func(msg interface{}, _ string, _ *service.Destination) error { 503 dispatched = true 504 result, ok := msg.(*Request) 505 require.True(t, ok) 506 require.Equal(t, expected, result.Label) 507 return nil 508 }, 509 } 510 511 _, encKey := newSigningAndEncryptionDIDKeys(t, tc.ctx) 512 513 inv := newOOBInvite(tc.ctx.mediaTypeProfiles, newServiceBlock([]string{encKey}, []string{encKey}, 514 didServiceType)) 515 inv.MyLabel = expected 516 _, _, action, e := (&requested{}).ExecuteInbound(&stateMachineMsg{ 517 DIDCommMsg: service.NewDIDCommMsgMap(inv), 518 connRecord: &connection.Record{}, 519 }, "", tc.ctx) 520 require.NoError(t, e) 521 require.NotNil(t, action) 522 err = action() 523 require.NoError(t, err) 524 require.True(t, dispatched) 525 }) 526 } 527 }) 528 t.Run("handle inbound oob invitations - register recipient keys in router", func(t *testing.T) { 529 registered := false 530 tests := []struct { 531 name string 532 ctx *context 533 }{ 534 { 535 name: "using context with ED25519 main VM and X25519 keyAgreement", 536 ctx: getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp), 537 }, 538 { 539 name: "using context with P-256 main VM and P-256 keyAgreement", 540 ctx: getContext(t, &prov, kms.ECDSAP256TypeIEEEP1363, kms.NISTP256ECDHKWType, mtp), 541 }, 542 { 543 name: "using context with P-384 main VM and P-384 keyAgreement", 544 ctx: getContext(t, &prov, kms.ECDSAP384TypeIEEEP1363, kms.NISTP384ECDHKWType, mtp), 545 }, 546 { 547 name: "using context with P-521 main VM and P-521 keyAgreement", 548 ctx: getContext(t, &prov, kms.ECDSAP521TypeIEEEP1363, kms.NISTP521ECDHKWType, mtp), 549 }, 550 { 551 name: "using context with ED25519 main VM and P-384 keyAgreement", 552 ctx: getContext(t, &prov, kms.ED25519Type, kms.NISTP384ECDHKWType, mtp), 553 }, 554 } 555 556 for _, tt := range tests { 557 tc := tt 558 t.Run(tc.name, func(t *testing.T) { 559 _, expected := newSigningAndEncryptionDIDKeys(t, tc.ctx) 560 _, encKey := newSigningAndEncryptionDIDKeys(t, tc.ctx) 561 562 doc := createDIDDoc(t, tc.ctx) 563 564 if didServiceType == vdrapi.DIDCommV2ServiceType { 565 expected = doc.KeyAgreement[0].VerificationMethod.ID 566 567 doc.Service = []diddoc.Service{{ 568 Type: didServiceType, 569 ServiceEndpoint: commonmodel.NewDIDCommV2Endpoint([]commonmodel.DIDCommV2Endpoint{ 570 {URI: "http://test.com", Accept: []string{"didcomm/v2"}}, 571 }), 572 RecipientKeys: []string{expected}, 573 }} 574 } else { 575 doc.Service = []diddoc.Service{{ 576 Type: didServiceType, 577 ServiceEndpoint: commonmodel.NewDIDCommV1Endpoint("http://test.com"), 578 RecipientKeys: []string{expected}, 579 }} 580 } 581 582 tc.ctx.vdRegistry = &mockvdr.MockVDRegistry{ 583 CreateValue: doc, 584 } 585 586 tc.ctx.routeSvc = &mockroute.MockMediatorSvc{ 587 Connections: []string{"xyz"}, 588 RoutingKeys: []string{expected}, 589 RouterEndpoint: "http://blah.com", 590 AddKeyFunc: func(result string) error { 591 require.Equal(t, expected, result) 592 registered = true 593 return nil 594 }, 595 } 596 _, _, _, err = (&requested{}).ExecuteInbound(&stateMachineMsg{ 597 options: &options{routerConnections: []string{"xyz"}}, 598 DIDCommMsg: service.NewDIDCommMsgMap(newOOBInvite( 599 tc.ctx.mediaTypeProfiles, 600 newServiceBlock([]string{encKey}, []string{encKey}, didServiceType))), 601 connRecord: &connection.Record{}, 602 }, "", tc.ctx) 603 require.NoError(t, err) 604 require.True(t, registered) 605 }) 606 } 607 }) 608 t.Run("handle inbound oob invitations - use routing info to create my did", func(t *testing.T) { 609 expected := mediator.NewConfig("http://test.com", []string{"my-test-key"}) 610 created := false 611 tests := []struct { 612 name string 613 ctx *context 614 }{ 615 { 616 name: "using context with ED25519 main VM and X25519 keyAgreement", 617 ctx: getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp), 618 }, 619 { 620 name: "using context with P-256 main VM and P-256 keyAgreement", 621 ctx: getContext(t, &prov, kms.ECDSAP256TypeIEEEP1363, kms.NISTP256ECDHKWType, mtp), 622 }, 623 { 624 name: "using context with P-384 main VM and P-384 keyAgreement", 625 ctx: getContext(t, &prov, kms.ECDSAP384TypeIEEEP1363, kms.NISTP384ECDHKWType, mtp), 626 }, 627 { 628 name: "using context with P-521 main VM and P-521 keyAgreement", 629 ctx: getContext(t, &prov, kms.ECDSAP521TypeIEEEP1363, kms.NISTP521ECDHKWType, mtp), 630 }, 631 { 632 name: "using context with ED25519 main VM and P-384 keyAgreement", 633 ctx: getContext(t, &prov, kms.ED25519Type, kms.NISTP384ECDHKWType, mtp), 634 }, 635 } 636 637 for _, tt := range tests { 638 tc := tt 639 t.Run(tc.name, func(t *testing.T) { 640 _, encKey := newSigningAndEncryptionDIDKeys(t, tc.ctx) 641 642 tc.ctx.routeSvc = &mockroute.MockMediatorSvc{ 643 Connections: []string{"xyz"}, 644 RouterEndpoint: expected.Endpoint(), 645 RoutingKeys: expected.Keys(), 646 } 647 648 docResolution := createDIDDoc(t, tc.ctx) 649 tc.ctx.vdRegistry = &mockvdr.MockVDRegistry{ 650 CreateFunc: func(_ string, didDoc *diddoc.Doc, 651 options ...vdrapi.DIDMethodOption) (*diddoc.DocResolution, error) { 652 created = true 653 654 uri, e := didDoc.Service[0].ServiceEndpoint.URI() 655 require.NoError(t, e) 656 require.Equal(t, expected.Endpoint(), uri) 657 return &diddoc.DocResolution{DIDDocument: docResolution}, nil 658 }, 659 ResolveValue: docResolution, 660 } 661 662 oobInvite := newOOBInvite(tc.ctx.mediaTypeProfiles, newServiceBlock( 663 []string{encKey}, []string{encKey}, didServiceType)) 664 _, _, _, err = (&requested{}).ExecuteInbound(&stateMachineMsg{ 665 options: &options{routerConnections: []string{"xyz"}}, 666 DIDCommMsg: service.NewDIDCommMsgMap(oobInvite), 667 connRecord: &connection.Record{}, 668 }, "", tc.ctx) 669 require.NoError(t, err) 670 require.True(t, created) 671 672 // try with target as string 673 oobInvite.Target = docResolution.ID 674 _, _, _, err = (&requested{}).ExecuteInbound(&stateMachineMsg{ 675 options: &options{routerConnections: []string{"xyz"}}, 676 DIDCommMsg: service.NewDIDCommMsgMap(oobInvite), 677 connRecord: &connection.Record{}, 678 }, "", tc.ctx) 679 require.NoError(t, err) 680 require.True(t, created) 681 }) 682 } 683 }) 684 t.Run("handling invitations fails if my diddoc does not have a valid didcomm service", func(t *testing.T) { 685 msg, e := service.ParseDIDCommMsgMap(invitationPayloadBytes) 686 require.NoError(t, e) 687 tests := []struct { 688 name string 689 ctx *context 690 }{ 691 { 692 name: "using context with ED25519 main VM and X25519 keyAgreement", 693 ctx: getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp), 694 }, 695 { 696 name: "using context with P-256 main VM and P-256 keyAgreement", 697 ctx: getContext(t, &prov, kms.ECDSAP256TypeIEEEP1363, kms.NISTP256ECDHKWType, mtp), 698 }, 699 { 700 name: "using context with P-384 main VM and P-384 keyAgreement", 701 ctx: getContext(t, &prov, kms.ECDSAP384TypeIEEEP1363, kms.NISTP384ECDHKWType, mtp), 702 }, 703 { 704 name: "using context with P-521 main VM and P-521 keyAgreement", 705 ctx: getContext(t, &prov, kms.ECDSAP521TypeIEEEP1363, kms.NISTP521ECDHKWType, mtp), 706 }, 707 { 708 name: "using context with ED25519 main VM and P-384 keyAgreement", 709 ctx: getContext(t, &prov, kms.ED25519Type, kms.NISTP384ECDHKWType, mtp), 710 }, 711 } 712 713 for _, tt := range tests { 714 tc := tt 715 t.Run(tc.name, func(t *testing.T) { 716 myDoc := createDIDDoc(t, tc.ctx) 717 myDoc.Service = []diddoc.Service{{ 718 ID: uuid.New().String(), 719 Type: "invalid", 720 Priority: 0, 721 RecipientKeys: nil, 722 ServiceEndpoint: commonmodel.NewDIDCommV2Endpoint([]commonmodel.DIDCommV2Endpoint{{}}), 723 }} 724 tc.ctx.vdRegistry = &mockvdr.MockVDRegistry{CreateValue: myDoc} 725 _, _, _, err = (&requested{}).ExecuteInbound(&stateMachineMsg{ 726 DIDCommMsg: msg, 727 connRecord: &connection.Record{}, 728 }, "", tc.ctx) 729 require.Error(t, err) 730 }) 731 } 732 }) 733 t.Run("handling OOB invitations fails if my diddoc does not have a valid didcomm service", func(t *testing.T) { 734 tests := []struct { 735 name string 736 ctx *context 737 }{ 738 { 739 name: "using context with ED25519 main VM and X25519 keyAgreement", 740 ctx: getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp), 741 }, 742 { 743 name: "using context with P-256 main VM and P-256 keyAgreement", 744 ctx: getContext(t, &prov, kms.ECDSAP256TypeIEEEP1363, kms.NISTP256ECDHKWType, mtp), 745 }, 746 { 747 name: "using context with P-384 main VM and P-384 keyAgreement", 748 ctx: getContext(t, &prov, kms.ECDSAP384TypeIEEEP1363, kms.NISTP384ECDHKWType, mtp), 749 }, 750 { 751 name: "using context with P-521 main VM and P-521 keyAgreement", 752 ctx: getContext(t, &prov, kms.ECDSAP521TypeIEEEP1363, kms.NISTP521ECDHKWType, mtp), 753 }, 754 { 755 name: "using context with ED25519 main VM and P-384 keyAgreement", 756 ctx: getContext(t, &prov, kms.ED25519Type, kms.NISTP384ECDHKWType, mtp), 757 }, 758 } 759 760 for _, tt := range tests { 761 tc := tt 762 t.Run(tc.name, func(t *testing.T) { 763 myDoc := createDIDDoc(t, tc.ctx) 764 myDoc.Service = []diddoc.Service{{ 765 ID: uuid.New().String(), 766 Type: "invalid", 767 Priority: 0, 768 RecipientKeys: nil, 769 ServiceEndpoint: commonmodel.NewDIDCommV2Endpoint([]commonmodel.DIDCommV2Endpoint{{}}), 770 }} 771 tc.ctx.vdRegistry = &mockvdr.MockVDRegistry{CreateValue: myDoc} 772 _, _, _, err = (&requested{}).ExecuteInbound(&stateMachineMsg{ 773 DIDCommMsg: service.NewDIDCommMsgMap(&OOBInvitation{ 774 ID: uuid.New().String(), 775 Type: oobMsgType, 776 ThreadID: uuid.New().String(), 777 TheirLabel: "test", 778 Target: &diddoc.Service{ 779 ID: uuid.New().String(), 780 Type: didServiceType, 781 Priority: 0, 782 RecipientKeys: []string{"key"}, 783 ServiceEndpoint: commonmodel.NewDIDCommV1Endpoint("http://test.com"), 784 }, 785 }), 786 connRecord: &connection.Record{}, 787 }, "", tc.ctx) 788 require.EqualError(t, err, "failed to handle inbound oob invitation : getting recipient key:"+ 789 " recipientKeyAsDIDKey: invalid DID Doc service type: 'invalid'") 790 }) 791 } 792 }) 793 t.Run("inbound oob request error", func(t *testing.T) { 794 _, _, _, err = (&requested{}).ExecuteInbound(&stateMachineMsg{ 795 DIDCommMsg: service.DIDCommMsgMap{ 796 "@type": oobMsgType, 797 "@id": map[int]int{}, 798 }, 799 connRecord: &connection.Record{}, 800 }, "", &context{}) 801 require.Error(t, err) 802 require.Contains(t, err.Error(), "failed to decode oob invitation: 1 error(s) decoding") 803 }) 804 t.Run("inbound request unmarshalling error", func(t *testing.T) { 805 _, followup, _, err := (&requested{}).ExecuteInbound(&stateMachineMsg{ 806 DIDCommMsg: service.DIDCommMsgMap{ 807 "@type": InvitationMsgType, 808 "@id": map[int]int{}, 809 }, 810 }, "", &context{}) 811 require.Error(t, err) 812 require.Contains(t, err.Error(), "JSON unmarshalling of invitation") 813 require.Nil(t, followup) 814 }) 815 t.Run("create DID error", func(t *testing.T) { 816 ctx2 := &context{ 817 outboundDispatcher: prov.OutboundDispatcher(), 818 vdRegistry: &mockvdr.MockVDRegistry{CreateErr: fmt.Errorf("create DID error")}, 819 } 820 didDoc, err := ctx2.vdRegistry.Create(testMethod, nil) 821 require.Error(t, err) 822 require.Contains(t, err.Error(), "create DID error") 823 require.Nil(t, didDoc) 824 }) 825 } 826 } 827 828 func TestRespondedState_Execute(t *testing.T) { 829 mtps := []string{transport.MediaTypeDIDCommV2Profile, transport.MediaTypeRFC0019EncryptedEnvelope} 830 831 for _, mtp := range mtps { 832 prov := getProvider(t) 833 tests := []struct { 834 name string 835 ctx *context 836 }{ 837 { 838 name: fmt.Sprintf("using context with ED25519 main VM and X25519 keyAgreement with profile %s", mtp), 839 ctx: getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp), 840 }, 841 { 842 name: fmt.Sprintf("using context with P-256 main VM and P-256 keyAgreement with profile %s", mtp), 843 ctx: getContext(t, &prov, kms.ECDSAP256TypeIEEEP1363, kms.NISTP256ECDHKWType, mtp), 844 }, 845 { 846 name: fmt.Sprintf("using context with P-384 main VM and P-384 keyAgreement with profile %s", mtp), 847 ctx: getContext(t, &prov, kms.ECDSAP384TypeIEEEP1363, kms.NISTP384ECDHKWType, mtp), 848 }, 849 { 850 name: fmt.Sprintf("using context with P-521 main VM and P-521 keyAgreement with profile %s", mtp), 851 ctx: getContext(t, &prov, kms.ECDSAP521TypeIEEEP1363, kms.NISTP521ECDHKWType, mtp), 852 }, 853 { 854 name: fmt.Sprintf("using context with ED25519 main VM and P-384 keyAgreement with profile %s", mtp), 855 ctx: getContext(t, &prov, kms.ED25519Type, kms.NISTP384ECDHKWType, mtp), 856 }, 857 } 858 859 for _, tt := range tests { 860 tc := tt 861 t.Run(tc.name, func(t *testing.T) { 862 request, err := createRequest(t, tc.ctx, false, mtp) 863 require.NoError(t, err) 864 requestPayloadBytes, err := json.Marshal(request) 865 require.NoError(t, err) 866 response, err := createResponse(request, tc.ctx) 867 require.NoErrorf(t, err, fmt.Sprintf("for %s", tc.name)) 868 responsePayloadBytes, err := json.Marshal(response) 869 require.NoError(t, err) 870 871 t.Run("rejects messages other than requests and responses", func(t *testing.T) { 872 others := []service.DIDCommMsg{ 873 service.NewDIDCommMsgMap(Invitation{Type: InvitationMsgType}), 874 service.NewDIDCommMsgMap(model.Ack{Type: AckMsgType}), 875 } 876 for _, msg := range others { 877 _, _, _, e := (&responded{}).ExecuteInbound(&stateMachineMsg{ 878 DIDCommMsg: msg, 879 }, "", &context{}) 880 require.Error(t, e) 881 require.Contains(t, e.Error(), "illegal msg type") 882 } 883 }) 884 t.Run("no followup for inbound requests", func(t *testing.T) { 885 connRec, followup, _, e := (&responded{}).ExecuteInbound(&stateMachineMsg{ 886 DIDCommMsg: bytesToDIDCommMsg(t, requestPayloadBytes), 887 connRecord: &connection.Record{}, 888 }, "", tc.ctx) 889 require.NoError(t, e) 890 require.NotNil(t, connRec) 891 require.IsType(t, &noOp{}, followup) 892 }) 893 t.Run("followup to 'completed' on inbound responses", func(t *testing.T) { 894 connRec := &connection.Record{ 895 State: (&responded{}).Name(), 896 ThreadID: request.ID, 897 ConnectionID: "123", 898 Namespace: findNamespace(ResponseMsgType), 899 } 900 err = tc.ctx.connectionRecorder.SaveConnectionRecordWithMappings(connRec) 901 require.NoError(t, err) 902 connRec, followup, _, e := (&responded{}).ExecuteInbound( 903 &stateMachineMsg{ 904 DIDCommMsg: bytesToDIDCommMsg(t, responsePayloadBytes), 905 connRecord: connRec, 906 }, "", tc.ctx) 907 require.NoError(t, e) 908 require.NotNil(t, connRec) 909 require.Equal(t, (&completed{}).Name(), followup.Name()) 910 }) 911 912 t.Run("handle inbound request unmarshalling error", func(t *testing.T) { 913 _, followup, _, err := (&responded{}).ExecuteInbound(&stateMachineMsg{ 914 DIDCommMsg: service.DIDCommMsgMap{"@id": map[int]int{}, "@type": RequestMsgType}, 915 }, "", &context{}) 916 require.Error(t, err) 917 require.Contains(t, err.Error(), "JSON unmarshalling of request") 918 require.Nil(t, followup) 919 }) 920 921 t.Run("fails if my did has an invalid didcomm service entry", func(t *testing.T) { 922 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp) 923 myDoc := createDIDDoc(t, ctx) 924 myDoc.Service = []diddoc.Service{{ 925 ID: uuid.New().String(), 926 Type: "invalid", 927 Priority: 0, 928 RecipientKeys: nil, 929 ServiceEndpoint: commonmodel.NewDIDCommV2Endpoint([]commonmodel.DIDCommV2Endpoint{{}}), 930 }} 931 ctx.vdRegistry = &mockvdr.MockVDRegistry{CreateValue: myDoc} 932 _, _, _, err := (&responded{}).ExecuteInbound(&stateMachineMsg{ 933 DIDCommMsg: bytesToDIDCommMsg(t, requestPayloadBytes), 934 connRecord: &connection.Record{}, 935 }, "", ctx) 936 require.Error(t, err) 937 }) 938 }) 939 } 940 } 941 } 942 943 func TestAbandonedState_Execute(t *testing.T) { 944 t.Run("execute abandon state", func(t *testing.T) { 945 connRec, _, _, err := (&abandoned{}).ExecuteInbound(&stateMachineMsg{ 946 DIDCommMsg: service.NewDIDCommMsgMap(Response{Type: ResponseMsgType}), 947 }, "", &context{}) 948 require.Error(t, err) 949 require.Contains(t, err.Error(), "not implemented") 950 require.Nil(t, connRec) 951 }) 952 } 953 954 // completed is an end state. 955 func TestCompletedState_Execute(t *testing.T) { 956 prov := getProvider(t) 957 customKMS := newKMS(t, prov.StoreProvider) 958 ctx := &context{ 959 crypto: &tinkcrypto.Crypto{}, 960 kms: customKMS, 961 keyType: kms.ED25519Type, 962 keyAgreementType: kms.X25519ECDHKWType, 963 } 964 pubKey, encKey := newSigningAndEncryptionDIDKeys(t, ctx) 965 connRec, err := connection.NewRecorder(&prov) 966 967 require.NoError(t, err) 968 require.NotNil(t, connRec) 969 970 ctx.connectionRecorder = connRec 971 972 newDIDDoc := createDIDDocWithKey(pubKey, encKey, transport.MediaTypeRFC0019EncryptedEnvelope) 973 974 invitation, err := createMockInvitation(pubKey, ctx) 975 require.NoError(t, err) 976 977 didKey, err := ctx.getVerKey(invitation.ID) 978 require.NoError(t, err) 979 980 docAttach, err := ctx.didDocAttachment(newDIDDoc, didKey) 981 require.NoError(t, err) 982 983 response := &Response{ 984 Type: ResponseMsgType, 985 ID: randomString(), 986 DocAttach: docAttach, 987 DID: newDIDDoc.ID, 988 Thread: &decorator.Thread{ 989 ID: "test", 990 }, 991 } 992 responsePayloadBytes, err := json.Marshal(response) 993 require.NoError(t, err) 994 995 t.Run("no followup for inbound responses", func(t *testing.T) { 996 connRec := &connection.Record{ 997 State: (&responded{}).Name(), 998 ThreadID: response.Thread.ID, 999 ConnectionID: "123", 1000 MyDID: "did:peer:123456789abcdefghi#inbox", 1001 Namespace: myNSPrefix, 1002 InvitationID: invitation.ID, 1003 RecipientKeys: []string{pubKey}, 1004 } 1005 err = ctx.connectionRecorder.SaveConnectionRecordWithMappings(connRec) 1006 require.NoError(t, err) 1007 ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveValue: mockdiddoc.GetMockDIDDoc(t, false)} 1008 require.NoError(t, err) 1009 _, followup, _, e := (&completed{}).ExecuteInbound(&stateMachineMsg{ 1010 DIDCommMsg: bytesToDIDCommMsg(t, responsePayloadBytes), 1011 connRecord: connRec, 1012 }, "", ctx) 1013 require.NoError(t, e) 1014 require.IsType(t, &noOp{}, followup) 1015 }) 1016 t.Run("no followup for inbound acks", func(t *testing.T) { 1017 connRec := &connection.Record{ 1018 State: (&responded{}).Name(), 1019 ThreadID: response.Thread.ID, 1020 ConnectionID: "123", 1021 Namespace: findNamespace(AckMsgType), 1022 RecipientKeys: []string{pubKey}, 1023 } 1024 err = ctx.connectionRecorder.SaveConnectionRecordWithMappings(connRec) 1025 require.NoError(t, err) 1026 ack := &model.Ack{ 1027 Type: AckMsgType, 1028 ID: randomString(), 1029 Status: ackStatusOK, 1030 Thread: &decorator.Thread{ 1031 ID: response.Thread.ID, 1032 }, 1033 } 1034 ackPayloadBytes, e := json.Marshal(ack) 1035 require.NoError(t, e) 1036 _, followup, _, e := (&completed{}).ExecuteInbound(&stateMachineMsg{ 1037 DIDCommMsg: bytesToDIDCommMsg(t, ackPayloadBytes), 1038 }, "", ctx) 1039 require.NoError(t, e) 1040 require.IsType(t, &noOp{}, followup) 1041 }) 1042 t.Run("no followup for inbound complete", func(t *testing.T) { 1043 connRec := &connection.Record{ 1044 State: (&responded{}).Name(), 1045 ThreadID: response.Thread.ID, 1046 ConnectionID: "123", 1047 Namespace: findNamespace(AckMsgType), 1048 RecipientKeys: []string{pubKey}, 1049 } 1050 err = ctx.connectionRecorder.SaveConnectionRecordWithMappings(connRec) 1051 require.NoError(t, err) 1052 complete := &Complete{ 1053 Type: CompleteMsgType, 1054 ID: randomString(), 1055 Thread: &decorator.Thread{ 1056 ID: response.Thread.ID, 1057 }, 1058 } 1059 // without connection record 1060 payloadBytes, e := json.Marshal(complete) 1061 require.NoError(t, e) 1062 _, followup, _, e := (&completed{}).ExecuteInbound(&stateMachineMsg{ 1063 DIDCommMsg: bytesToDIDCommMsg(t, payloadBytes), 1064 }, "", ctx) 1065 require.NoError(t, e) 1066 require.IsType(t, &noOp{}, followup) 1067 // with connection record 1068 connRec.TheirDID = "did:abc:test123" 1069 _, followup, _, e = (&completed{}).ExecuteInbound(&stateMachineMsg{ 1070 DIDCommMsg: bytesToDIDCommMsg(t, payloadBytes), 1071 connRecord: connRec, 1072 }, "", ctx) 1073 require.NoError(t, e) 1074 require.IsType(t, &noOp{}, followup) 1075 // with connection record with sov interop fix 1076 connRec.TheirDID = "test123" 1077 ctx.doACAPyInterop = true 1078 _, followup, _, e = (&completed{}).ExecuteInbound(&stateMachineMsg{ 1079 DIDCommMsg: bytesToDIDCommMsg(t, payloadBytes), 1080 connRecord: connRec, 1081 }, "", ctx) 1082 require.NoError(t, e) 1083 require.IsType(t, &noOp{}, followup) 1084 ctx.doACAPyInterop = false 1085 }) 1086 t.Run("rejects messages other than responses, acks, and completes", func(t *testing.T) { 1087 others := []service.DIDCommMsg{ 1088 service.NewDIDCommMsgMap(Invitation{Type: InvitationMsgType}), 1089 service.NewDIDCommMsgMap(Request{Type: RequestMsgType}), 1090 } 1091 1092 for _, msg := range others { 1093 _, _, _, err = (&completed{}).ExecuteInbound(&stateMachineMsg{ 1094 DIDCommMsg: msg, 1095 }, "", &context{}) 1096 require.Error(t, err) 1097 require.Contains(t, err.Error(), "illegal msg type") 1098 } 1099 }) 1100 t.Run("no followup for inbound responses unmarshalling error", func(t *testing.T) { 1101 _, followup, _, err := (&completed{}).ExecuteInbound(&stateMachineMsg{ 1102 DIDCommMsg: service.DIDCommMsgMap{"@id": map[int]int{}, "@type": ResponseMsgType}, 1103 }, "", &context{}) 1104 require.Error(t, err) 1105 require.Contains(t, err.Error(), "JSON unmarshalling of response") 1106 require.Nil(t, followup) 1107 }) 1108 t.Run("inbound completes unmarshalling error", func(t *testing.T) { 1109 _, followup, _, err := (&completed{}).ExecuteInbound(&stateMachineMsg{ 1110 DIDCommMsg: service.DIDCommMsgMap{"@id": map[int]int{}, "@type": CompleteMsgType}, 1111 }, "", &context{}) 1112 require.Error(t, err) 1113 require.Contains(t, err.Error(), "JSON unmarshalling of complete") 1114 require.Nil(t, followup) 1115 }) 1116 t.Run("execute inbound handle inbound response error", func(t *testing.T) { 1117 response.DID = "" 1118 responsePayloadBytes, err := json.Marshal(response) 1119 require.NoError(t, err) 1120 _, followup, _, err := (&completed{}).ExecuteInbound(&stateMachineMsg{ 1121 DIDCommMsg: bytesToDIDCommMsg(t, responsePayloadBytes), 1122 }, "", ctx) 1123 require.Error(t, err) 1124 require.Contains(t, err.Error(), "handle inbound response") 1125 require.Nil(t, followup) 1126 }) 1127 } 1128 1129 func TestNewRequestFromInvitation(t *testing.T) { 1130 invitation := &Invitation{ 1131 Type: InvitationMsgType, 1132 ID: randomString(), 1133 Label: "Bob", 1134 RecipientKeys: []string{"8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K"}, 1135 ServiceEndpoint: "https://localhost:8090", 1136 RoutingKeys: []string{"8HH5gYEeNc3z7PYXmd54d4x6qAfCNrqQqEB3nS7Zfu7K"}, 1137 } 1138 1139 t.Run("successful new request from invitation", func(t *testing.T) { 1140 prov := getProvider(t) 1141 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1142 _, connRec, err := ctx.handleInboundInvitation(invitation, invitation.ID, &options{}, &connection.Record{}) 1143 require.NoError(t, err) 1144 require.NotNil(t, connRec.MyDID) 1145 }) 1146 t.Run("successful response to invitation with public did", func(t *testing.T) { 1147 prov := getProvider(t) 1148 ctx := &context{ 1149 kms: prov.CustomKMS, 1150 keyType: kms.ED25519Type, 1151 keyAgreementType: kms.X25519ECDHKWType, 1152 mediaTypeProfiles: []string{transport.MediaTypeRFC0019EncryptedEnvelope}, 1153 } 1154 doc := createDIDDoc(t, ctx) 1155 connRec, err := connection.NewRecorder(&protocol.MockProvider{}) 1156 require.NoError(t, err) 1157 didConnStore, err := didstore.NewConnectionStore(&protocol.MockProvider{}) 1158 require.NoError(t, err) 1159 1160 ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveValue: doc} 1161 ctx.connectionRecorder = connRec 1162 ctx.connectionStore = didConnStore 1163 1164 _, connRecord, err := ctx.handleInboundInvitation(invitation, invitation.ID, &options{publicDID: doc.ID}, 1165 &connection.Record{}) 1166 require.NoError(t, err) 1167 require.NotNil(t, connRecord.MyDID) 1168 require.Equal(t, connRecord.MyDID, doc.ID) 1169 }) 1170 t.Run("successful response to invitation with public did using P-384 key type", func(t *testing.T) { 1171 prov := getProvider(t) 1172 ctx := &context{ 1173 kms: prov.CustomKMS, 1174 keyType: kms.ECDSAP384TypeIEEEP1363, 1175 keyAgreementType: kms.NISTP384ECDHKWType, 1176 mediaTypeProfiles: []string{transport.MediaTypeRFC0019EncryptedEnvelope}, 1177 } 1178 1179 doc := createDIDDoc(t, ctx) 1180 connRec, err := connection.NewRecorder(&protocol.MockProvider{}) 1181 require.NoError(t, err) 1182 didConnStore, err := didstore.NewConnectionStore(&protocol.MockProvider{}) 1183 require.NoError(t, err) 1184 1185 ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveValue: doc} 1186 ctx.connectionRecorder = connRec 1187 ctx.connectionStore = didConnStore 1188 1189 _, connRecord, err := ctx.handleInboundInvitation(invitation, invitation.ID, &options{publicDID: doc.ID}, 1190 &connection.Record{}) 1191 require.NoError(t, err) 1192 require.NotNil(t, connRecord.MyDID) 1193 require.Equal(t, connRecord.MyDID, doc.ID) 1194 }) 1195 t.Run("unsuccessful new request from invitation ", func(t *testing.T) { 1196 prov := protocol.MockProvider{} 1197 1198 customKMS := newKMS(t, mem.NewProvider()) 1199 1200 ctx := &context{ 1201 kms: customKMS, 1202 outboundDispatcher: prov.OutboundDispatcher(), 1203 routeSvc: &mockroute.MockMediatorSvc{}, 1204 vdRegistry: &mockvdr.MockVDRegistry{CreateErr: fmt.Errorf("create DID error")}, 1205 keyType: kms.ED25519Type, 1206 keyAgreementType: kms.X25519ECDHKWType, 1207 mediaTypeProfiles: []string{transport.MediaTypeRFC0019EncryptedEnvelope}, 1208 } 1209 _, connRec, err := ctx.handleInboundInvitation(invitation, invitation.ID, &options{}, &connection.Record{}) 1210 require.Error(t, err) 1211 require.Contains(t, err.Error(), "create DID error") 1212 require.Nil(t, connRec) 1213 }) 1214 t.Run("unsuccessful new request from invitation with P-384 key as KW", func(t *testing.T) { 1215 prov := protocol.MockProvider{} 1216 customKMS := newKMS(t, mem.NewProvider()) 1217 1218 ctx := &context{ 1219 kms: customKMS, 1220 outboundDispatcher: prov.OutboundDispatcher(), 1221 routeSvc: &mockroute.MockMediatorSvc{}, 1222 vdRegistry: &mockvdr.MockVDRegistry{CreateErr: fmt.Errorf("create DID error")}, 1223 keyType: kms.ED25519Type, 1224 keyAgreementType: kms.NISTP384ECDHKWType, 1225 mediaTypeProfiles: []string{transport.MediaTypeRFC0019EncryptedEnvelope}, 1226 } 1227 _, connRec, err := ctx.handleInboundInvitation(invitation, invitation.ID, &options{}, &connection.Record{}) 1228 require.Error(t, err) 1229 require.Contains(t, err.Error(), "create DID error") 1230 require.Nil(t, connRec) 1231 }) 1232 t.Run("unsuccessful new request from invitation (creating did doc attachment for request)", func(t *testing.T) { 1233 prov := getProvider(t) 1234 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1235 1236 ctx.doACAPyInterop = true 1237 ctx.crypto = &mockcrypto.Crypto{ 1238 SignErr: fmt.Errorf("sign error"), 1239 } 1240 1241 _, _, err := ctx.handleInboundInvitation(invitation, invitation.ID, &options{}, &connection.Record{}) 1242 require.Error(t, err) 1243 require.Contains(t, err.Error(), "creating did doc attachment for request") 1244 }) 1245 } 1246 1247 func TestNewResponseFromRequest(t *testing.T) { 1248 prov := getProvider(t) 1249 store := mockstorage.NewMockStoreProvider() 1250 k := newKMS(t, store) 1251 1252 t.Run("successful new response from request", func(t *testing.T) { 1253 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1254 request, err := createRequest(t, ctx, false, ctx.mediaTypeProfiles[0]) 1255 require.NoError(t, err) 1256 _, connRec, err := ctx.handleInboundRequest(request, &options{}, &connection.Record{}) 1257 require.NoError(t, err) 1258 require.NotNil(t, connRec.MyDID) 1259 require.NotNil(t, connRec.TheirDID) 1260 }) 1261 1262 t.Run("unsuccessful new response from request due to resolve DID error", func(t *testing.T) { 1263 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1264 request, err := createRequest(t, ctx, false, transport.MediaTypeRFC0019EncryptedEnvelope) 1265 require.NoError(t, err) 1266 1267 request.DID = "" 1268 1269 _, connRec, err := ctx.handleInboundRequest(request, &options{}, &connection.Record{}) 1270 require.Error(t, err) 1271 require.Contains(t, err.Error(), "resolve did doc from exchange request") 1272 require.Nil(t, connRec) 1273 }) 1274 1275 t.Run("unsuccessful new response from request due to create did error", func(t *testing.T) { 1276 didDoc := mockdiddoc.GetMockDIDDoc(t, false) 1277 ctx := &context{ 1278 vdRegistry: &mockvdr.MockVDRegistry{ 1279 CreateErr: fmt.Errorf("create DID error"), 1280 ResolveValue: mockdiddoc.GetMockDIDDoc(t, false), 1281 }, 1282 routeSvc: &mockroute.MockMediatorSvc{}, 1283 } 1284 request := &Request{ 1285 DID: didDoc.ID, 1286 DocAttach: signedDocAttach(t, didDoc), 1287 } 1288 _, connRec, err := ctx.handleInboundRequest(request, &options{}, &connection.Record{}) 1289 require.Error(t, err) 1290 require.Contains(t, err.Error(), "create DID error") 1291 require.Nil(t, connRec) 1292 }) 1293 1294 t.Run("unsuccessful new response from request due to get did doc error", func(t *testing.T) { 1295 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1296 ctx.connectionStore = &mockConnectionStore{saveDIDFromDocErr: fmt.Errorf("save did error")} 1297 1298 request, err := createRequest(t, ctx, false, transport.MediaTypeRFC0019EncryptedEnvelope) 1299 require.NoError(t, err) 1300 _, connRec, err := ctx.handleInboundRequest(request, &options{}, &connection.Record{}) 1301 require.Error(t, err) 1302 require.Contains(t, err.Error(), "get response did doc and connection") 1303 require.Nil(t, connRec) 1304 }) 1305 1306 t.Run("unsuccessful new response from request due to sign error", func(t *testing.T) { 1307 connRec, err := connection.NewRecorder(&prov) 1308 require.NoError(t, err) 1309 require.NotNil(t, connRec) 1310 1311 didConnStore, err := didstore.NewConnectionStore(&prov) 1312 require.NoError(t, err) 1313 require.NotNil(t, didConnStore) 1314 1315 ctx := &context{ 1316 vdRegistry: &mockvdr.MockVDRegistry{CreateValue: mockdiddoc.GetMockDIDDoc(t, false)}, 1317 crypto: &mockcrypto.Crypto{SignErr: errors.New("sign error")}, 1318 connectionRecorder: connRec, 1319 connectionStore: didConnStore, 1320 routeSvc: &mockroute.MockMediatorSvc{}, 1321 kms: prov.CustomKMS, 1322 keyType: kms.ED25519Type, 1323 keyAgreementType: kms.X25519ECDHKWType, 1324 doACAPyInterop: true, 1325 } 1326 1327 request, err := createRequest(t, ctx, true, transport.MediaTypeRFC0019EncryptedEnvelope) 1328 require.NoError(t, err) 1329 1330 _, connRecord, err := ctx.handleInboundRequest(request, &options{}, &connection.Record{}) 1331 1332 require.Error(t, err) 1333 require.Contains(t, err.Error(), "sign error") 1334 require.Nil(t, connRecord) 1335 }) 1336 1337 t.Run("unsuccessful new response from request due to resolve public did from request error", func(t *testing.T) { 1338 ctx := &context{vdRegistry: &mockvdr.MockVDRegistry{ResolveErr: errors.New("resolver error")}} 1339 request := &Request{DID: "did:sidetree:abc"} 1340 _, _, err := ctx.handleInboundRequest(request, &options{}, &connection.Record{}) 1341 require.Error(t, err) 1342 require.Contains(t, err.Error(), "resolver error") 1343 }) 1344 1345 t.Run("unsuccessful new response from request due to invalid did for creating destination", func(t *testing.T) { 1346 mockDoc := newPeerDID(t, k) 1347 mockDoc.Service = nil 1348 1349 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1350 1351 request, err := createRequest(t, ctx, false, transport.MediaTypeRFC0019EncryptedEnvelope) 1352 require.NoError(t, err) 1353 1354 request.DID = mockDoc.ID 1355 request.DocAttach = unsignedDocAttach(t, mockDoc) 1356 1357 _, _, err = ctx.handleInboundRequest(request, &options{}, &connection.Record{}) 1358 require.Error(t, err) 1359 require.Contains(t, err.Error(), "missing DID doc service") 1360 }) 1361 } 1362 1363 func TestPrepareResponse(t *testing.T) { 1364 prov := getProvider(t) 1365 1366 t.Run("successful new response from request", func(t *testing.T) { 1367 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1368 request, err := createRequest(t, ctx, false, transport.MediaTypeRFC0019EncryptedEnvelope) 1369 require.NoError(t, err) 1370 1371 _, err = ctx.prepareResponse(request, mockdiddoc.GetMockDIDDoc(t, false)) 1372 require.NoError(t, err) 1373 }) 1374 1375 t.Run("successful new response from request, in interop mode", func(t *testing.T) { 1376 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1377 ctx.doACAPyInterop = true 1378 1379 request, err := createRequest(t, ctx, false, transport.MediaTypeRFC0019EncryptedEnvelope) 1380 require.NoError(t, err) 1381 1382 _, err = ctx.prepareResponse(request, mockdiddoc.GetMockDIDDoc(t, false)) 1383 require.NoError(t, err) 1384 }) 1385 1386 t.Run("wraps error from connection store", func(t *testing.T) { 1387 expected := errors.New("test") 1388 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1389 ctx.doACAPyInterop = true 1390 1391 pr := testProvider() 1392 pr.StoreProvider = &mockstorage.MockStoreProvider{ 1393 Store: &mockstorage.MockStore{ 1394 Store: make(map[string]mockstorage.DBEntry), 1395 ErrGet: expected, 1396 }, 1397 } 1398 1399 ctx.connectionRecorder = connRecorder(t, pr) 1400 1401 request, err := createRequest(t, ctx, false, transport.MediaTypeRFC0019EncryptedEnvelope) 1402 require.NoError(t, err) 1403 1404 _, err = ctx.prepareResponse(request, mockdiddoc.GetMockDIDDoc(t, false)) 1405 require.Error(t, err) 1406 require.True(t, errors.Is(err, expected)) 1407 }) 1408 1409 t.Run("failed fetch of doc signing key", func(t *testing.T) { 1410 expected := errors.New("test") 1411 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1412 ctx.doACAPyInterop = true 1413 1414 request, err := createRequest(t, ctx, false, transport.MediaTypeRFC0019EncryptedEnvelope) 1415 require.NoError(t, err) 1416 1417 ctx.kms = &mockkms.KeyManager{GetKeyErr: expected} 1418 1419 _, err = ctx.prepareResponse(request, mockdiddoc.GetMockDIDDoc(t, false)) 1420 require.Error(t, err) 1421 require.True(t, errors.Is(err, expected)) 1422 }) 1423 1424 t.Run("failed doc signing", func(t *testing.T) { 1425 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1426 ctx.doACAPyInterop = true 1427 1428 request, err := createRequest(t, ctx, false, transport.MediaTypeRFC0019EncryptedEnvelope) 1429 require.NoError(t, err) 1430 1431 // fails to do ed25519 sign with wrong type of key 1432 mockKey, err := mockkms.CreateMockAESGCMKeyHandle() 1433 require.NoError(t, err) 1434 1435 ctx.kms = &mockkms.KeyManager{GetKeyValue: mockKey} 1436 1437 _, err = ctx.prepareResponse(request, mockdiddoc.GetMockDIDDoc(t, false)) 1438 require.Error(t, err) 1439 }) 1440 } 1441 1442 func TestContext_DIDDocAttachment(t *testing.T) { 1443 prov := getProvider(t) 1444 1445 t.Run("successful new did doc attachment without signing", func(t *testing.T) { 1446 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1447 1448 doc := mockdiddoc.GetMockDIDDoc(t, false) 1449 1450 att, err := ctx.didDocAttachment(doc, "") 1451 require.NoError(t, err) 1452 1453 attData, err := att.Data.Fetch() 1454 require.NoError(t, err) 1455 1456 checkDoc, err := diddoc.ParseDocument(attData) 1457 require.NoError(t, err) 1458 require.NotNil(t, checkDoc) 1459 1460 require.Equal(t, checkDoc.ID, doc.ID) 1461 }) 1462 1463 t.Run("successful new did doc attachment with signing", func(t *testing.T) { 1464 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1465 ctx.doACAPyInterop = true 1466 1467 doc := mockdiddoc.GetMockDIDDoc(t, false) 1468 1469 _, pub, err := ctx.kms.CreateAndExportPubKeyBytes(kms.ED25519Type) 1470 require.NoError(t, err) 1471 1472 didKey, _ := fingerprint.CreateDIDKey(pub) 1473 1474 att, err := ctx.didDocAttachment(doc, didKey) 1475 require.NoError(t, err) 1476 1477 attData, err := att.Data.Fetch() 1478 require.NoError(t, err) 1479 1480 checkDoc, err := diddoc.ParseDocument(attData) 1481 require.NoError(t, err) 1482 require.NotNil(t, checkDoc) 1483 1484 require.Equal(t, checkDoc.ID, doc.ID) 1485 }) 1486 1487 t.Run("fail to create did doc attachment, invalid key", func(t *testing.T) { 1488 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1489 ctx.doACAPyInterop = true 1490 1491 doc := mockdiddoc.GetMockDIDDoc(t, false) 1492 1493 _, err := ctx.didDocAttachment(doc, "did:key:not a did key") 1494 require.Error(t, err) 1495 require.Contains(t, err.Error(), "failed to extract pubKeyBytes") 1496 }) 1497 1498 t.Run("fail to create did doc attachment, can't create KID", func(t *testing.T) { 1499 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1500 ctx.doACAPyInterop = true 1501 1502 doc := mockdiddoc.GetMockDIDDoc(t, false) 1503 1504 didKey, _ := fingerprint.CreateDIDKey([]byte{}) 1505 1506 _, err := ctx.didDocAttachment(doc, didKey) 1507 require.Error(t, err) 1508 require.Contains(t, err.Error(), "failed to generate KID from public key") 1509 }) 1510 } 1511 1512 func TestResolvePublicKey(t *testing.T) { 1513 prov := getProvider(t) 1514 1515 t.Run("resolve key from did:key", func(t *testing.T) { 1516 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1517 1518 keyBytes := []byte("12345678123456781234567812345678") 1519 didKey, _ := fingerprint.CreateDIDKey(keyBytes) 1520 1521 pub, err := ctx.resolvePublicKey(didKey) 1522 require.NoError(t, err) 1523 require.EqualValues(t, keyBytes, pub) 1524 }) 1525 1526 t.Run("resolve key reference from doc in vdr", func(t *testing.T) { 1527 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1528 doc := mockdiddoc.GetMockDIDDoc(t, false) 1529 ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveValue: doc} 1530 1531 vm := doc.VerificationMethod[0] 1532 1533 pub, err := ctx.resolvePublicKey(vm.ID) 1534 require.NoError(t, err) 1535 require.EqualValues(t, vm.Value, pub) 1536 }) 1537 1538 t.Run("fail to resolve public key from unknown kid", func(t *testing.T) { 1539 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1540 1541 _, err := ctx.resolvePublicKey("something something") 1542 require.Error(t, err) 1543 require.Contains(t, err.Error(), "failed to resolve public key value from kid") 1544 }) 1545 1546 t.Run("fail to resolve public key from invalid did:key", func(t *testing.T) { 1547 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1548 1549 _, err := ctx.resolvePublicKey("did:key:not a did key") 1550 require.Error(t, err) 1551 require.Contains(t, err.Error(), "failed to extract pubKeyBytes") 1552 }) 1553 1554 t.Run("fail to resolve doc for key reference", func(t *testing.T) { 1555 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1556 doc := mockdiddoc.GetMockDIDDoc(t, false) 1557 1558 vm := doc.VerificationMethod[0] 1559 1560 _, err := ctx.resolvePublicKey(vm.ID) 1561 require.Error(t, err) 1562 require.Contains(t, err.Error(), "failed to resolve public did") 1563 }) 1564 1565 t.Run("fail to find key in resolved doc", func(t *testing.T) { 1566 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1567 doc := mockdiddoc.GetMockDIDDoc(t, false) 1568 ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveValue: doc} 1569 1570 kid := doc.VerificationMethod[0].ID 1571 1572 doc.VerificationMethod[0].ID = "wrong-key-id" 1573 1574 _, err := ctx.resolvePublicKey(kid) 1575 require.Error(t, err) 1576 require.Contains(t, err.Error(), "failed to lookup public key") 1577 }) 1578 } 1579 1580 func TestResolveDIDDocFromMessage(t *testing.T) { 1581 prov := getProvider(t) 1582 mtps := []string{transport.MediaTypeDIDCommV2Profile, transport.MediaTypeRFC0019EncryptedEnvelope} 1583 1584 for _, mtp := range mtps { 1585 t.Run(fmt.Sprintf("success with media type profile: %s", mtp), func(t *testing.T) { 1586 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp) 1587 docIn := mockdiddoc.GetMockDIDDoc(t, false) 1588 1589 att, err := ctx.didDocAttachment(docIn, "") 1590 require.NoError(t, err) 1591 1592 doc, err := ctx.resolveDidDocFromMessage(docIn.ID, att) 1593 require.NoError(t, err) 1594 1595 require.Equal(t, docIn.ID, doc.ID) 1596 }) 1597 1598 t.Run(fmt.Sprintf("success - public resolution with media type profile: %s", mtp), func(t *testing.T) { 1599 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp) 1600 docIn := mockdiddoc.GetMockDIDDoc(t, false) 1601 docIn.ID = "did:remote:abc" 1602 1603 ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveValue: docIn} 1604 1605 doc, err := ctx.resolveDidDocFromMessage(docIn.ID, nil) 1606 require.NoError(t, err) 1607 1608 require.Equal(t, docIn.ID, doc.ID) 1609 }) 1610 1611 t.Run(fmt.Sprintf("failure - can't do public resolution with media type profile: %s", mtp), 1612 func(t *testing.T) { 1613 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp) 1614 docIn := mockdiddoc.GetMockDIDDoc(t, false) 1615 docIn.ID = "did:remote:abc" 1616 1617 ctx.vdRegistry = &mockvdr.MockVDRegistry{ResolveErr: fmt.Errorf("resolve error")} 1618 1619 _, err := ctx.resolveDidDocFromMessage(docIn.ID, nil) 1620 require.Error(t, err) 1621 require.Contains(t, err.Error(), "failed to resolve public did") 1622 }) 1623 1624 t.Run(fmt.Sprintf("failure - can't parse did with media type profile: %s", mtp), func(t *testing.T) { 1625 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp) 1626 _, err := ctx.resolveDidDocFromMessage("blah blah", nil) 1627 require.Error(t, err) 1628 require.Contains(t, err.Error(), "failed to parse did") 1629 }) 1630 1631 t.Run(fmt.Sprintf("failure - missing attachment for private did with media type profile: %s", mtp), 1632 func(t *testing.T) { 1633 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp) 1634 _, err := ctx.resolveDidDocFromMessage("did:peer:abcdefg", nil) 1635 require.Error(t, err) 1636 require.Contains(t, err.Error(), "missing did_doc~attach") 1637 }) 1638 1639 t.Run(fmt.Sprintf("failure - bad base64 data in attachment with media type profile: %s", mtp), 1640 func(t *testing.T) { 1641 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp) 1642 1643 att := decorator.Attachment{Data: decorator.AttachmentData{Base64: "!@#$%^&*"}} 1644 1645 _, err := ctx.resolveDidDocFromMessage("did:peer:abcdefg", &att) 1646 require.Error(t, err) 1647 require.Contains(t, err.Error(), "failed to parse base64 attachment data") 1648 }) 1649 1650 t.Run(fmt.Sprintf("failure - attachment contains encoded broken document with media type profile: %s", 1651 mtp), func(t *testing.T) { 1652 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp) 1653 1654 att := decorator.Attachment{ 1655 Data: decorator.AttachmentData{ 1656 Base64: base64.StdEncoding.EncodeToString([]byte("abcdefg")), 1657 }, 1658 } 1659 1660 _, err := ctx.resolveDidDocFromMessage("did:peer:abcdefg", &att) 1661 require.Error(t, err) 1662 require.Contains(t, err.Error(), "failed to parse did document") 1663 }) 1664 1665 t.Run(fmt.Sprintf("success - interop mode with media type profile: %s", mtp), func(t *testing.T) { 1666 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp) 1667 1668 docIn := mockdiddoc.GetMockDIDDoc(t, false) 1669 docIn.ID = "did:sov:abcdefg" 1670 1671 att, err := ctx.didDocAttachment(docIn, "") 1672 require.NoError(t, err) 1673 1674 ctx.doACAPyInterop = true 1675 1676 doc, err := ctx.resolveDidDocFromMessage(docIn.ID, att) 1677 require.NoError(t, err) 1678 1679 require.Equal(t, docIn.ID, doc.ID) 1680 }) 1681 1682 t.Run(fmt.Sprintf("failure - can't store document locally with media type profile: %s", mtp), 1683 func(t *testing.T) { 1684 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, mtp) 1685 1686 ctx.vdRegistry = &mockvdr.MockVDRegistry{CreateErr: fmt.Errorf("create error")} 1687 1688 docIn := mockdiddoc.GetMockDIDDoc(t, false) 1689 1690 att, err := ctx.didDocAttachment(docIn, "") 1691 require.NoError(t, err) 1692 1693 _, err = ctx.resolveDidDocFromMessage(docIn.ID, att) 1694 require.Error(t, err) 1695 require.Contains(t, err.Error(), "failed to store provided did document") 1696 }) 1697 } 1698 } 1699 1700 func TestHandleInboundResponse(t *testing.T) { 1701 prov := getProvider(t) 1702 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1703 _, encKey := newSigningAndEncryptionDIDKeys(t, ctx) 1704 1705 _, err := createMockInvitation(encKey, ctx) 1706 require.NoError(t, err) 1707 1708 t.Run("handle inbound responses get connection record error", func(t *testing.T) { 1709 response := &Response{Thread: &decorator.Thread{ID: "test"}} 1710 _, connRec, e := ctx.handleInboundResponse(response) 1711 require.Error(t, e) 1712 require.Contains(t, e.Error(), "get connection record") 1713 require.Nil(t, connRec) 1714 }) 1715 t.Run("handle inbound responses get connection record error", func(t *testing.T) { 1716 response := &Response{Thread: &decorator.Thread{ID: ""}} 1717 _, connRec, e := ctx.handleInboundResponse(response) 1718 require.Error(t, e) 1719 require.Contains(t, e.Error(), "empty bytes") 1720 require.Nil(t, connRec) 1721 }) 1722 } 1723 1724 func TestGetInvitationRecipientKey(t *testing.T) { 1725 prov := getProvider(t) 1726 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1727 1728 t.Run("successfully getting invitation recipient key", func(t *testing.T) { 1729 invitation := &Invitation{ 1730 Type: InvitationMsgType, 1731 ID: randomString(), 1732 Label: "Bob", 1733 RecipientKeys: []string{"test"}, 1734 ServiceEndpoint: "http://alice.agent.example.com:8081", 1735 } 1736 recKey, err := ctx.getInvitationRecipientKey(invitation) 1737 require.NoError(t, err) 1738 require.Equal(t, invitation.RecipientKeys[0], recKey) 1739 }) 1740 t.Run("failed to get invitation recipient key", func(t *testing.T) { 1741 doc := mockdiddoc.GetMockDIDDoc(t, false) 1742 _, ok := diddoc.LookupService(doc, "did-communication") 1743 require.True(t, ok) 1744 ctx := context{vdRegistry: &mockvdr.MockVDRegistry{ResolveValue: doc}} 1745 invitation := &Invitation{ 1746 Type: InvitationMsgType, 1747 ID: randomString(), 1748 DID: doc.ID, 1749 } 1750 recKey, err := ctx.getInvitationRecipientKey(invitation) 1751 require.NoError(t, err) 1752 // TODO fix hardcode base58 https://github.com/hyperledger/aries-framework-go/issues/1207 1753 require.Equal(t, doc.Service[0].RecipientKeys[0], recKey) 1754 }) 1755 t.Run("failed to get invitation recipient key", func(t *testing.T) { 1756 invitation := &Invitation{ 1757 Type: InvitationMsgType, 1758 ID: randomString(), 1759 DID: "test", 1760 } 1761 _, err := ctx.getInvitationRecipientKey(invitation) 1762 require.Error(t, err) 1763 require.Contains(t, err.Error(), "get invitation recipient key: DID does not exist") 1764 }) 1765 } 1766 1767 func TestGetPublicKey(t *testing.T) { 1768 k := newKMS(t, mockstorage.NewMockStoreProvider()) 1769 t.Run("successfully getting public key by id", func(t *testing.T) { 1770 prov := protocol.MockProvider{CustomKMS: k} 1771 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1772 doc, err := ctx.vdRegistry.Create(testMethod, nil) 1773 require.NoError(t, err) 1774 pubkey, ok := diddoc.LookupPublicKey(doc.DIDDocument.VerificationMethod[0].ID, doc.DIDDocument) 1775 require.True(t, ok) 1776 require.NotNil(t, pubkey) 1777 }) 1778 t.Run("failed to get public key", func(t *testing.T) { 1779 prov := protocol.MockProvider{CustomKMS: k} 1780 ctx := getContext(t, &prov, kms.ED25519Type, kms.X25519ECDHKWType, transport.MediaTypeRFC0019EncryptedEnvelope) 1781 doc, err := ctx.vdRegistry.Create(testMethod, nil) 1782 require.NoError(t, err) 1783 pubkey, ok := diddoc.LookupPublicKey("invalid-key", doc.DIDDocument) 1784 require.False(t, ok) 1785 require.Nil(t, pubkey) 1786 }) 1787 } 1788 1789 func TestGetDIDDocAndConnection(t *testing.T) { 1790 k := newKMS(t, mockstorage.NewMockStoreProvider()) 1791 ctx := &context{ 1792 kms: k, 1793 keyType: kms.ED25519Type, 1794 keyAgreementType: kms.X25519ECDHKWType, 1795 mediaTypeProfiles: []string{transport.MediaTypeRFC0019EncryptedEnvelope}, 1796 } 1797 1798 t.Run("successfully getting did doc and connection for public did", func(t *testing.T) { 1799 doc := createDIDDoc(t, ctx) 1800 connRec, err := connection.NewRecorder(&protocol.MockProvider{}) 1801 require.NoError(t, err) 1802 didConnStore, err := didstore.NewConnectionStore(&protocol.MockProvider{}) 1803 require.NoError(t, err) 1804 ctx := context{ 1805 vdRegistry: &mockvdr.MockVDRegistry{ResolveValue: doc}, 1806 connectionRecorder: connRec, 1807 connectionStore: didConnStore, 1808 } 1809 didDoc, err := ctx.getMyDIDDoc(doc.ID, nil, "") 1810 require.NoError(t, err) 1811 require.NotNil(t, didDoc) 1812 }) 1813 t.Run("error getting public did doc from resolver", func(t *testing.T) { 1814 ctx := context{ 1815 vdRegistry: &mockvdr.MockVDRegistry{ResolveErr: errors.New("resolver error")}, 1816 } 1817 didDoc, err := ctx.getMyDIDDoc("did-id", nil, "") 1818 require.Error(t, err) 1819 require.Contains(t, err.Error(), "resolver error") 1820 require.Nil(t, didDoc) 1821 }) 1822 t.Run("error creating peer did", func(t *testing.T) { 1823 customKMS := newKMS(t, mockstorage.NewMockStoreProvider()) 1824 ctx := context{ 1825 kms: customKMS, 1826 vdRegistry: &mockvdr.MockVDRegistry{CreateErr: errors.New("creator error")}, 1827 routeSvc: &mockroute.MockMediatorSvc{}, 1828 keyType: kms.ED25519Type, 1829 keyAgreementType: kms.X25519ECDHKWType, 1830 } 1831 didDoc, err := ctx.getMyDIDDoc("", nil, didCommServiceType) 1832 require.Error(t, err) 1833 require.Contains(t, err.Error(), "creator error") 1834 require.Nil(t, didDoc) 1835 }) 1836 t.Run("successfully created peer did", func(t *testing.T) { 1837 connRec, err := connection.NewRecorder(&protocol.MockProvider{}) 1838 require.NoError(t, err) 1839 didConnStore, err := didstore.NewConnectionStore(&protocol.MockProvider{}) 1840 require.NoError(t, err) 1841 customKMS := newKMS(t, mockstorage.NewMockStoreProvider()) 1842 ctx := context{ 1843 kms: customKMS, 1844 vdRegistry: &mockvdr.MockVDRegistry{CreateValue: mockdiddoc.GetMockDIDDoc(t, false)}, 1845 connectionRecorder: connRec, 1846 connectionStore: didConnStore, 1847 routeSvc: &mockroute.MockMediatorSvc{}, 1848 keyType: kms.ED25519Type, 1849 keyAgreementType: kms.X25519ECDHKWType, 1850 } 1851 didDoc, err := ctx.getMyDIDDoc("", nil, didCommV2ServiceType) 1852 require.NoError(t, err) 1853 require.NotNil(t, didDoc) 1854 }) 1855 1856 t.Run("successfully created peer did with didcomm V2 service bloc", func(t *testing.T) { 1857 connRec, err := connection.NewRecorder(&protocol.MockProvider{}) 1858 require.NoError(t, err) 1859 didConnStore, err := didstore.NewConnectionStore(&protocol.MockProvider{}) 1860 require.NoError(t, err) 1861 customKMS := newKMS(t, mockstorage.NewMockStoreProvider()) 1862 ctx := context{ 1863 kms: customKMS, 1864 vdRegistry: &mockvdr.MockVDRegistry{CreateValue: mockdiddoc.GetMockDIDDocWithDIDCommV2Bloc(t, "bob")}, 1865 connectionRecorder: connRec, 1866 connectionStore: didConnStore, 1867 routeSvc: &mockroute.MockMediatorSvc{}, 1868 keyType: kms.ED25519Type, 1869 keyAgreementType: kms.X25519ECDHKWType, 1870 } 1871 didDoc, err := ctx.getMyDIDDoc("", []string{"did:peer:bob"}, didCommV2ServiceType) 1872 require.NoError(t, err) 1873 require.NotNil(t, didDoc) 1874 }) 1875 t.Run("test create did doc - router service config error", func(t *testing.T) { 1876 connRec, err := connection.NewRecorder(&protocol.MockProvider{}) 1877 require.NoError(t, err) 1878 customKMS := newKMS(t, mockstorage.NewMockStoreProvider()) 1879 ctx := context{ 1880 kms: customKMS, 1881 vdRegistry: &mockvdr.MockVDRegistry{CreateValue: mockdiddoc.GetMockDIDDoc(t, false)}, 1882 connectionRecorder: connRec, 1883 routeSvc: &mockroute.MockMediatorSvc{ 1884 Connections: []string{"xyz"}, 1885 ConfigErr: errors.New("router config error"), 1886 }, 1887 } 1888 didDoc, err := ctx.getMyDIDDoc("", []string{"xyz"}, "") 1889 require.Error(t, err) 1890 require.Contains(t, err.Error(), "did doc - fetch router config") 1891 require.Nil(t, didDoc) 1892 }) 1893 1894 t.Run("test create did doc - router service config error", func(t *testing.T) { 1895 connRec, err := connection.NewRecorder(&protocol.MockProvider{}) 1896 require.NoError(t, err) 1897 customKMS := newKMS(t, mockstorage.NewMockStoreProvider()) 1898 ctx := context{ 1899 kms: customKMS, 1900 vdRegistry: &mockvdr.MockVDRegistry{CreateValue: mockdiddoc.GetMockDIDDoc(t, false)}, 1901 connectionRecorder: connRec, 1902 routeSvc: &mockroute.MockMediatorSvc{ 1903 Connections: []string{"xyz"}, 1904 AddKeyErr: errors.New("router add key error"), 1905 }, 1906 keyType: kms.ED25519Type, 1907 keyAgreementType: kms.X25519ECDHKWType, 1908 } 1909 didDoc, err := ctx.getMyDIDDoc("", []string{"xyz"}, "") 1910 require.Error(t, err) 1911 require.Contains(t, err.Error(), "did doc - add key to the router") 1912 require.Nil(t, didDoc) 1913 }) 1914 1915 t.Run("error - invalid service type", func(t *testing.T) { 1916 connRec, err := connection.NewRecorder(&protocol.MockProvider{}) 1917 require.NoError(t, err) 1918 didConnStore, err := didstore.NewConnectionStore(&protocol.MockProvider{}) 1919 require.NoError(t, err) 1920 customKMS := newKMS(t, mockstorage.NewMockStoreProvider()) 1921 ctx := context{ 1922 kms: customKMS, 1923 vdRegistry: &mockvdr.MockVDRegistry{CreateValue: mockdiddoc.GetMockDIDDoc(t, false)}, 1924 connectionRecorder: connRec, 1925 connectionStore: didConnStore, 1926 routeSvc: &mockroute.MockMediatorSvc{}, 1927 keyType: kms.ED25519Type, 1928 keyAgreementType: kms.X25519ECDHKWType, 1929 } 1930 didDoc, err := ctx.getMyDIDDoc("", nil, "") 1931 require.Error(t, err) 1932 require.Nil(t, didDoc) 1933 require.Contains(t, err.Error(), "getMyDIDDoc: invalid DID Doc service type: ''") 1934 }) 1935 } 1936 1937 const sovDoc = `{ 1938 "@context": "https://www.w3.org/2019/did/v1", 1939 "id": "did:sov:17hRTxZFuRqqwFPxXnnuLj", 1940 "service": [ 1941 { 1942 "type": "endpoint", 1943 "serviceEndpoint": "http://172.17.0.1:9031" 1944 } 1945 ], 1946 "authentication": [ 1947 { 1948 "type": "Ed25519SignatureAuthentication2018", 1949 "publicKey": [ 1950 "did:sov:17hRTxZFuRqqwFPxXnnuLj#key-1" 1951 ] 1952 } 1953 ], 1954 "publicKey": [ 1955 { 1956 "id": "did:sov:17hRTxZFuRqqwFPxXnnuLj#key-1", 1957 "type": "Ed25519VerificationKey2018", 1958 "publicKeyBase58": "14ehnBh9oevUhQUADCRk5dmMCk3cmLukZcKNCTxLGiic" 1959 } 1960 ] 1961 }` 1962 1963 func TestGetServiceBlock(t *testing.T) { 1964 doc, err := diddoc.ParseDocument([]byte(sovDoc)) 1965 require.NoError(t, err) 1966 1967 v := &mockvdr.MockVDRegistry{ResolveValue: doc} 1968 1969 t.Run("success: get service block from public sov did", func(t *testing.T) { 1970 ctx := &context{ 1971 doACAPyInterop: true, 1972 vdRegistry: v, 1973 } 1974 1975 inv := newOOBInvite([]string{transport.MediaTypeRFC0019EncryptedEnvelope}, doc.ID) 1976 1977 svc, err := ctx.getServiceBlock(inv) 1978 require.NoError(t, err) 1979 require.Len(t, svc.RecipientKeys, 1) 1980 }) 1981 1982 t.Run("failure: get service block from public sov did, not in interop mode", func(t *testing.T) { 1983 ctx := &context{ 1984 vdRegistry: v, 1985 } 1986 1987 inv := newOOBInvite([]string{transport.MediaTypeRFC0019EncryptedEnvelope}, doc.ID) 1988 1989 svc, err := ctx.getServiceBlock(inv) 1990 require.Error(t, err) 1991 require.Nil(t, svc) 1992 require.Contains(t, err.Error(), "no valid service block found") 1993 }) 1994 1995 t.Run("failure: get service block from public sov did, doc does not have endpoint service", func(t *testing.T) { 1996 doc2, err := diddoc.ParseDocument([]byte(sovDoc)) 1997 require.NoError(t, err) 1998 1999 doc2.Service = nil 2000 2001 ctx := &context{ 2002 vdRegistry: &mockvdr.MockVDRegistry{ResolveValue: doc2}, 2003 doACAPyInterop: true, 2004 } 2005 2006 inv := newOOBInvite([]string{transport.MediaTypeRFC0019EncryptedEnvelope}, doc.ID) 2007 2008 svc, err := ctx.getServiceBlock(inv) 2009 require.Error(t, err) 2010 require.Nil(t, svc) 2011 require.Contains(t, err.Error(), "failed to get interop doc service") 2012 }) 2013 } 2014 2015 func TestGetVerKey(t *testing.T) { 2016 k := newKMS(t, mockstorage.NewMockStoreProvider()) 2017 ctx := &context{ 2018 kms: k, 2019 keyType: kms.ED25519Type, 2020 keyAgreementType: kms.X25519ECDHKWType, 2021 mediaTypeProfiles: []string{transport.MediaTypeRFC0019EncryptedEnvelope}, 2022 } 2023 2024 _, encKey := newSigningAndEncryptionDIDKeys(t, ctx) 2025 2026 t.Run("returns verkey from explicit oob invitation", func(t *testing.T) { 2027 expected := newServiceBlock([]string{encKey}, []string{encKey}, didCommServiceType) 2028 invitation := newOOBInvite(expected.Accept, expected) 2029 ctx.connectionRecorder = connRecorder(t, testProvider()) 2030 2031 err := ctx.connectionRecorder.SaveInvitation(invitation.ThreadID, invitation) 2032 require.NoError(t, err) 2033 2034 result, err := ctx.getVerKey(invitation.ThreadID) 2035 require.NoError(t, err) 2036 require.Equal(t, expected.RecipientKeys[0], result) 2037 2038 expected = newServiceBlock([]string{encKey}, []string{encKey}, didCommV2ServiceType) 2039 accept, err := expected.ServiceEndpoint.Accept() 2040 require.NoError(t, err) 2041 invitation = newOOBInvite(accept, expected) 2042 ctx.connectionRecorder = connRecorder(t, testProvider()) 2043 2044 err = ctx.connectionRecorder.SaveInvitation(invitation.ThreadID, invitation) 2045 require.NoError(t, err) 2046 2047 result, err = ctx.getVerKey(invitation.ThreadID) 2048 require.NoError(t, err) 2049 require.Equal(t, expected.RecipientKeys[0], result) 2050 }) 2051 t.Run("returns verkey from implicit oob invitation", func(t *testing.T) { 2052 publicDID := createDIDDoc(t, ctx) 2053 invitation := newOOBInvite([]string{ctx.mediaTypeProfiles[0]}, publicDID.ID) 2054 ctx.connectionRecorder = connRecorder(t, testProvider()) 2055 ctx.vdRegistry = &mockvdr.MockVDRegistry{ 2056 ResolveValue: publicDID, 2057 } 2058 2059 err := ctx.connectionRecorder.SaveInvitation(invitation.ThreadID, invitation) 2060 require.NoError(t, err) 2061 2062 result, err := ctx.getVerKey(invitation.ThreadID) 2063 require.NoError(t, err) 2064 require.Equal(t, publicDID.Service[0].RecipientKeys[0], result) 2065 }) 2066 2067 t.Run("returns verkey from implicit (interop) oob invitation", func(t *testing.T) { 2068 publicDID, err := diddoc.ParseDocument([]byte(sovDoc)) 2069 require.NoError(t, err) 2070 invitation := newOOBInvite([]string{transport.MediaTypeRFC0019EncryptedEnvelope}, publicDID.ID) 2071 ctx.connectionRecorder = connRecorder(t, testProvider()) 2072 ctx.vdRegistry = &mockvdr.MockVDRegistry{ 2073 ResolveValue: publicDID, 2074 } 2075 ctx.doACAPyInterop = true 2076 2077 err = ctx.connectionRecorder.SaveInvitation(invitation.ThreadID, invitation) 2078 require.NoError(t, err) 2079 2080 result, err := ctx.getVerKey(invitation.ThreadID) 2081 require.NoError(t, err) 2082 require.Equal(t, publicDID.Service[0].RecipientKeys[0], result) 2083 2084 ctx.doACAPyInterop = false 2085 }) 2086 2087 t.Run("returns verkey from explicit didexchange invitation", func(t *testing.T) { 2088 expected := newServiceBlock([]string{encKey}, []string{encKey}, didCommServiceType) 2089 invitation := newDidExchangeInvite(t, "", expected) 2090 ctx.connectionRecorder = connRecorder(t, testProvider()) 2091 2092 err := ctx.connectionRecorder.SaveInvitation(invitation.ID, invitation) 2093 require.NoError(t, err) 2094 2095 result, err := ctx.getVerKey(invitation.ID) 2096 require.NoError(t, err) 2097 require.Equal(t, expected.RecipientKeys[0], result) 2098 2099 expected = newServiceBlock([]string{encKey}, []string{encKey}, didCommV2ServiceType) 2100 invitation = newDidExchangeInvite(t, "", expected) 2101 ctx.connectionRecorder = connRecorder(t, testProvider()) 2102 2103 err = ctx.connectionRecorder.SaveInvitation(invitation.ID, invitation) 2104 require.NoError(t, err) 2105 2106 result, err = ctx.getVerKey(invitation.ID) 2107 require.NoError(t, err) 2108 require.Equal(t, expected.RecipientKeys[0], result) 2109 }) 2110 2111 t.Run("returns verkey from implicit didexchange invitation", func(t *testing.T) { 2112 publicDID := createDIDDoc(t, ctx) 2113 ctx.connectionRecorder = connRecorder(t, testProvider()) 2114 ctx.vdRegistry = &mockvdr.MockVDRegistry{ 2115 ResolveValue: publicDID, 2116 } 2117 2118 svc, found := diddoc.LookupService(publicDID, "did-communication") 2119 require.True(t, found) 2120 2121 result, err := ctx.getVerKey(publicDID.ID) 2122 require.NoError(t, err) 2123 require.Equal(t, svc.RecipientKeys[0], result) 2124 }) 2125 2126 t.Run("fails for oob invitation with no target", func(t *testing.T) { 2127 invalid := newOOBInvite(nil, nil) 2128 ctx.connectionRecorder = connRecorder(t, testProvider()) 2129 2130 err := ctx.connectionRecorder.SaveInvitation(invalid.ThreadID, invalid) 2131 require.NoError(t, err) 2132 2133 _, err = ctx.getVerKey(invalid.ThreadID) 2134 require.Error(t, err) 2135 }) 2136 2137 t.Run("wraps error from store", func(t *testing.T) { 2138 expected := errors.New("test") 2139 pr := testProvider() 2140 pr.StoreProvider = &mockstorage.MockStoreProvider{ 2141 Store: &mockstorage.MockStore{ 2142 Store: make(map[string]mockstorage.DBEntry), 2143 ErrGet: expected, 2144 }, 2145 } 2146 ctx.connectionRecorder = connRecorder(t, pr) 2147 2148 invitation := newOOBInvite([]string{transport.MediaTypeRFC0019EncryptedEnvelope}, 2149 newServiceBlock([]string{encKey}, []string{encKey}, didCommServiceType)) 2150 err := ctx.connectionRecorder.SaveInvitation(invitation.ID, invitation) 2151 require.NoError(t, err) 2152 2153 invitation = newOOBInvite([]string{transport.MediaTypeDIDCommV2Profile}, 2154 newServiceBlock([]string{encKey}, []string{encKey}, didCommV2ServiceType)) 2155 err = ctx.connectionRecorder.SaveInvitation(invitation.ID, invitation) 2156 require.NoError(t, err) 2157 2158 _, err = ctx.getVerKey(invitation.ID) 2159 require.Error(t, err) 2160 }) 2161 2162 t.Run("wraps error from vdr resolution", func(t *testing.T) { 2163 expected := errors.New("test") 2164 ctx.connectionRecorder = connRecorder(t, testProvider()) 2165 ctx.vdRegistry = &mockvdr.MockVDRegistry{ 2166 ResolveErr: expected, 2167 } 2168 2169 _, err := ctx.getVerKey("did:example:123") 2170 require.Error(t, err) 2171 require.True(t, errors.Is(err, expected)) 2172 }) 2173 } 2174 2175 func createDIDDoc(t *testing.T, ctx *context) *diddoc.Doc { 2176 t.Helper() 2177 2178 verDIDKey, encDIDKey := newSigningAndEncryptionDIDKeys(t, ctx) 2179 2180 return createDIDDocWithKey(verDIDKey, encDIDKey, ctx.mediaTypeProfiles[0]) 2181 } 2182 2183 func createDIDDocWithKey(verDIDKey, encDIDKey, mediaTypeProfile string) *diddoc.Doc { 2184 const ( 2185 didFormat = "did:%s:%s" 2186 didPKID = "%s#keys-%d" 2187 didServiceID = "%s#endpoint-%d" 2188 method = "test" 2189 ) 2190 2191 id := fmt.Sprintf(didFormat, method, verDIDKey[:16]) 2192 pubKeyID := fmt.Sprintf(didPKID, id, 1) 2193 verPubKeyVM := diddoc.VerificationMethod{ 2194 ID: pubKeyID, 2195 Type: "Ed25519VerificationKey2018", 2196 Controller: id, 2197 Value: []byte(verDIDKey), 2198 } 2199 2200 encPubKeyID := fmt.Sprintf(didPKID, id, 2) 2201 encKeyV := diddoc.Verification{ 2202 VerificationMethod: diddoc.VerificationMethod{ 2203 ID: encPubKeyID, 2204 Type: "X25519KeyAgreementKey2019", 2205 Controller: id, 2206 Value: []byte(encDIDKey), 2207 }, 2208 Relationship: diddoc.KeyAgreement, 2209 } 2210 2211 var ( 2212 didCommService string 2213 recKey string 2214 sp commonmodel.Endpoint 2215 ) 2216 2217 switch mediaTypeProfile { 2218 case transport.MediaTypeDIDCommV2Profile, transport.MediaTypeAIP2RFC0587Profile: 2219 didCommService = vdrapi.DIDCommV2ServiceType 2220 recKey = verDIDKey 2221 sp = commonmodel.NewDIDCommV2Endpoint([]commonmodel.DIDCommV2Endpoint{ 2222 {URI: "http://localhost:58416", Accept: []string{mediaTypeProfile}}, 2223 }) 2224 default: 2225 didCommService = vdrapi.DIDCommServiceType 2226 recKey = encPubKeyID 2227 sp = commonmodel.NewDIDCommV1Endpoint("http://localhost:58416") 2228 } 2229 2230 services := []diddoc.Service{ 2231 { 2232 ID: fmt.Sprintf(didServiceID, id, 1), 2233 Type: didCommService, 2234 ServiceEndpoint: sp, 2235 Priority: 0, 2236 RecipientKeys: []string{recKey}, 2237 }, 2238 } 2239 2240 switch mediaTypeProfile { 2241 case transport.MediaTypeDIDCommV2Profile, transport.MediaTypeAIP2RFC0587Profile: 2242 default: // set DIDComm V1 Accept field. 2243 services[0].Accept = []string{mediaTypeProfile} 2244 } 2245 2246 createdTime := time.Now() 2247 didDoc := &diddoc.Doc{ 2248 Context: []string{diddoc.ContextV1}, 2249 ID: id, 2250 VerificationMethod: []diddoc.VerificationMethod{verPubKeyVM, encKeyV.VerificationMethod}, 2251 KeyAgreement: []diddoc.Verification{encKeyV}, 2252 Service: services, 2253 Created: &createdTime, 2254 Updated: &createdTime, 2255 } 2256 2257 return didDoc 2258 } 2259 2260 func getProvider(t *testing.T) protocol.MockProvider { 2261 t.Helper() 2262 2263 store := &mockstorage.MockStore{Store: make(map[string]mockstorage.DBEntry)} 2264 sProvider := mockstorage.NewCustomMockStoreProvider(store) 2265 customKMS := newKMS(t, sProvider) 2266 2267 return protocol.MockProvider{ 2268 StoreProvider: sProvider, 2269 CustomKMS: customKMS, 2270 } 2271 } 2272 2273 func getContext(t *testing.T, prov *protocol.MockProvider, keyType, keyAgreementType kms.KeyType, 2274 mediaTypeProfile string) *context { 2275 t.Helper() 2276 2277 ctx := &context{ 2278 outboundDispatcher: prov.OutboundDispatcher(), 2279 crypto: &tinkcrypto.Crypto{}, 2280 routeSvc: &mockroute.MockMediatorSvc{}, 2281 kms: prov.KMS(), 2282 keyType: keyType, 2283 keyAgreementType: keyAgreementType, 2284 mediaTypeProfiles: []string{mediaTypeProfile}, 2285 } 2286 2287 pubKey, encKey := newSigningAndEncryptionDIDKeys(t, ctx) 2288 connRec, err := connection.NewRecorder(prov) 2289 require.NoError(t, err) 2290 2291 didConnStore, err := didstore.NewConnectionStore(prov) 2292 require.NoError(t, err) 2293 2294 ctx.vdRegistry = &mockvdr.MockVDRegistry{CreateValue: createDIDDocWithKey(pubKey, encKey, mediaTypeProfile)} 2295 ctx.connectionRecorder = connRec 2296 ctx.connectionStore = didConnStore 2297 2298 return ctx 2299 } 2300 2301 func createRequest(t *testing.T, ctx *context, signDoc bool, mediaTypeProfile string) (*Request, error) { 2302 t.Helper() 2303 2304 pubKey, encKey := newSigningAndEncryptionDIDKeys(t, ctx) 2305 2306 invitation, err := createMockInvitation(pubKey, ctx) 2307 if err != nil { 2308 return nil, err 2309 } 2310 2311 newDidDoc := createDIDDocWithKey(pubKey, encKey, mediaTypeProfile) 2312 2313 var att *decorator.Attachment 2314 if signDoc { 2315 att = signedDocAttach(t, newDidDoc) 2316 } else { 2317 att = unsignedDocAttach(t, newDidDoc) 2318 } 2319 2320 // Prepare did-exchange inbound request 2321 request := &Request{ 2322 Type: RequestMsgType, 2323 ID: randomString(), 2324 Label: "Bob", 2325 Thread: &decorator.Thread{ 2326 PID: invitation.ID, 2327 }, 2328 2329 DID: newDidDoc.ID, 2330 DocAttach: att, 2331 } 2332 2333 return request, nil 2334 } 2335 2336 func createResponse(request *Request, ctx *context) (*Response, error) { 2337 doc, err := ctx.vdRegistry.Create(testMethod, nil) 2338 if err != nil { 2339 return nil, err 2340 } 2341 2342 didKey, err := ctx.getVerKey(request.Thread.PID) 2343 if err != nil { 2344 return nil, err 2345 } 2346 2347 docAttach, err := ctx.didDocAttachment(doc.DIDDocument, didKey) 2348 if err != nil { 2349 return nil, err 2350 } 2351 2352 response := &Response{ 2353 Type: ResponseMsgType, 2354 ID: randomString(), 2355 Thread: &decorator.Thread{ 2356 ID: request.ID, 2357 }, 2358 DocAttach: docAttach, 2359 } 2360 2361 return response, nil 2362 } 2363 2364 func createMockInvitation(pubKey string, ctx *context) (*Invitation, error) { 2365 invitation := &Invitation{ 2366 Type: InvitationMsgType, 2367 ID: randomString(), 2368 Label: "Bob", 2369 RecipientKeys: []string{pubKey}, 2370 ServiceEndpoint: "http://alice.agent.example.com:8081", 2371 } 2372 2373 err := ctx.connectionRecorder.SaveInvitation(invitation.ID, invitation) 2374 if err != nil { 2375 return nil, err 2376 } 2377 2378 return invitation, nil 2379 } 2380 2381 func toDIDCommMsg(t *testing.T, v interface{}) service.DIDCommMsgMap { 2382 msg, err := service.ParseDIDCommMsgMap(toBytes(t, v)) 2383 require.NoError(t, err) 2384 2385 return msg 2386 } 2387 2388 func bytesToDIDCommMsg(t *testing.T, v []byte) service.DIDCommMsg { 2389 msg, err := service.ParseDIDCommMsgMap(v) 2390 require.NoError(t, err) 2391 2392 return msg 2393 } 2394 2395 func toBytes(t *testing.T, data interface{}) []byte { 2396 t.Helper() 2397 2398 src, err := json.Marshal(data) 2399 require.NoError(t, err) 2400 2401 return src 2402 } 2403 2404 func newDidExchangeInvite(t *testing.T, publicDID string, svc *diddoc.Service) *Invitation { 2405 t.Helper() 2406 2407 i := &Invitation{ 2408 ID: uuid.New().String(), 2409 Type: InvitationMsgType, 2410 DID: publicDID, 2411 } 2412 2413 if svc != nil { 2414 if svc.Type == didCommV2ServiceType { 2415 i.RecipientKeys = svc.RecipientKeys 2416 uri, err := svc.ServiceEndpoint.URI() 2417 require.NoError(t, err) 2418 2419 i.ServiceEndpoint = uri 2420 2421 routingKeys, err := svc.ServiceEndpoint.RoutingKeys() 2422 require.NoError(t, err) 2423 2424 i.RoutingKeys = routingKeys 2425 } else { 2426 var err error 2427 2428 i.RecipientKeys = svc.RecipientKeys 2429 i.ServiceEndpoint, err = svc.ServiceEndpoint.URI() 2430 require.NoError(t, err) 2431 i.RoutingKeys = svc.RoutingKeys 2432 } 2433 } 2434 2435 return i 2436 } 2437 2438 func newOOBInvite(accept []string, target interface{}) *OOBInvitation { 2439 return &OOBInvitation{ 2440 ID: uuid.New().String(), 2441 Type: oobMsgType, 2442 ThreadID: uuid.New().String(), 2443 TheirLabel: "test", 2444 Target: target, 2445 MediaTypeProfiles: accept, 2446 } 2447 } 2448 2449 func newServiceBlock(recKeys, routingKeys []string, didCommServiceVType string) *diddoc.Service { 2450 var ( 2451 sp commonmodel.Endpoint 2452 didCommV1RoutingKeys []string 2453 ) 2454 2455 switch didCommServiceVType { 2456 case didCommV2ServiceType: 2457 sp = commonmodel.NewDIDCommV2Endpoint([]commonmodel.DIDCommV2Endpoint{ 2458 {URI: "http://test.com", Accept: []string{transport.MediaTypeDIDCommV2Profile}, RoutingKeys: routingKeys}, 2459 }) 2460 default: 2461 sp = commonmodel.NewDIDCommV1Endpoint("http://test.com") 2462 didCommV1RoutingKeys = routingKeys 2463 } 2464 2465 svc := &diddoc.Service{ 2466 ID: uuid.New().String(), 2467 Type: didCommServiceVType, 2468 RecipientKeys: recKeys, 2469 ServiceEndpoint: sp, 2470 } 2471 2472 if didCommServiceVType == didCommServiceType { 2473 svc.Accept = []string{transport.MediaTypeRFC0019EncryptedEnvelope} 2474 svc.RoutingKeys = didCommV1RoutingKeys 2475 } 2476 2477 return svc 2478 } 2479 2480 func connRecorder(t *testing.T, p provider) *connection.Recorder { 2481 s, err := connection.NewRecorder(p) 2482 require.NoError(t, err) 2483 2484 return s 2485 }