Tapir provides a framework for building Anonymous / metadata resistant Services
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

65 lines
2.3 KiB

  1. package applications
  2. import (
  3. "cwtch.im/tapir"
  4. "cwtch.im/tapir/primitives/privacypass"
  5. "encoding/json"
  6. "git.openprivacy.ca/openprivacy/log"
  7. )
  8. // TokenApplication provides Tokens for PoW
  9. type TokenApplication struct {
  10. TranscriptApp
  11. TokenService *privacypass.TokenServer
  12. Tokens []*privacypass.Token
  13. }
  14. // HasTokensCapability is granted once the client has obtained signed tokens
  15. const HasTokensCapability = tapir.Capability("HasTokensCapability")
  16. const numTokens = 10
  17. // NewInstance should always return a new instantiation of the application.
  18. func (tokenapp *TokenApplication) NewInstance() tapir.Application {
  19. app := new(TokenApplication)
  20. app.TokenService = tokenapp.TokenService
  21. return app
  22. }
  23. // Init is run when the connection is first started.
  24. func (tokenapp *TokenApplication) Init(connection tapir.Connection) {
  25. tokenapp.Transcript().NewProtocol("token-app")
  26. log.Debugf(tokenapp.Transcript().OutputTranscriptToAudit())
  27. if connection.IsOutbound() {
  28. tokens, blinded := privacypass.GenerateBlindedTokenBatch(numTokens)
  29. data, _ := json.Marshal(blinded)
  30. connection.Send(data)
  31. var signedBatch privacypass.SignedBatchWithProof
  32. err := json.Unmarshal(connection.Expect(), &signedBatch)
  33. if err == nil {
  34. verified := privacypass.UnblindSignedTokenBatch(tokens, blinded, signedBatch.SignedTokens, tokenapp.TokenService.Y, signedBatch.Proof, tokenapp.Transcript())
  35. if verified {
  36. log.Debugf("Successfully obtained signed tokens")
  37. tokenapp.Tokens = tokens
  38. connection.SetCapability(HasTokensCapability)
  39. return
  40. }
  41. // This will close the connection by default and no tokens will be available.
  42. // This usecase can be checked by the existing WaitForCapabilityOrClose() function using the HasTokensCapability
  43. // If the connection closes without the HasTokensCapability then the error can be handled by whatever client needs it
  44. log.Debugf("Failed to verify signed token batch")
  45. }
  46. return
  47. }
  48. // We are the server
  49. var blinded []privacypass.BlindedToken
  50. err := json.Unmarshal(connection.Expect(), &blinded)
  51. if err == nil {
  52. batchProof := tokenapp.TokenService.SignBlindedTokenBatch(blinded, tokenapp.Transcript())
  53. log.Debugf(tokenapp.Transcript().OutputTranscriptToAudit())
  54. data, _ := json.Marshal(batchProof)
  55. connection.Send(data)
  56. return
  57. }
  58. }