2019-09-15 21:20:05 +00:00
|
|
|
package applications
|
|
|
|
|
|
|
|
import (
|
|
|
|
"cwtch.im/tapir"
|
|
|
|
"cwtch.im/tapir/primitives/privacypass"
|
|
|
|
"encoding/json"
|
2020-02-06 23:54:13 +00:00
|
|
|
"git.openprivacy.ca/openprivacy/log"
|
2019-09-15 21:20:05 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// TokenApplication provides Tokens for PoW
|
|
|
|
type TokenApplication struct {
|
|
|
|
TranscriptApp
|
|
|
|
TokenService *privacypass.TokenServer
|
|
|
|
Tokens []*privacypass.Token
|
|
|
|
}
|
|
|
|
|
|
|
|
// HasTokensCapability is granted once the client has obtained signed tokens
|
|
|
|
const HasTokensCapability = tapir.Capability("HasTokensCapability")
|
2019-11-27 23:15:33 +00:00
|
|
|
const numTokens = 10
|
2019-09-15 21:20:05 +00:00
|
|
|
|
|
|
|
// NewInstance should always return a new instantiation of the application.
|
2019-11-26 21:10:09 +00:00
|
|
|
func (tokenapp *TokenApplication) NewInstance() tapir.Application {
|
2019-09-15 21:20:05 +00:00
|
|
|
app := new(TokenApplication)
|
2019-11-26 21:10:09 +00:00
|
|
|
app.TokenService = tokenapp.TokenService
|
2019-09-15 21:20:05 +00:00
|
|
|
return app
|
|
|
|
}
|
|
|
|
|
|
|
|
// Init is run when the connection is first started.
|
2019-11-26 21:10:09 +00:00
|
|
|
func (tokenapp *TokenApplication) Init(connection tapir.Connection) {
|
|
|
|
tokenapp.Transcript().NewProtocol("token-app")
|
|
|
|
log.Debugf(tokenapp.Transcript().OutputTranscriptToAudit())
|
2019-09-15 21:20:05 +00:00
|
|
|
if connection.IsOutbound() {
|
2019-11-27 23:15:33 +00:00
|
|
|
tokens, blinded := privacypass.GenerateBlindedTokenBatch(numTokens)
|
2019-09-15 21:20:05 +00:00
|
|
|
data, _ := json.Marshal(blinded)
|
|
|
|
connection.Send(data)
|
|
|
|
var signedBatch privacypass.SignedBatchWithProof
|
|
|
|
err := json.Unmarshal(connection.Expect(), &signedBatch)
|
|
|
|
if err == nil {
|
2019-11-26 21:10:09 +00:00
|
|
|
verified := privacypass.UnblindSignedTokenBatch(tokens, blinded, signedBatch.SignedTokens, tokenapp.TokenService.Y, signedBatch.Proof, tokenapp.Transcript())
|
2019-09-15 21:20:05 +00:00
|
|
|
if verified {
|
|
|
|
log.Debugf("Successfully obtained signed tokens")
|
2019-11-26 21:10:09 +00:00
|
|
|
tokenapp.Tokens = tokens
|
2019-09-15 21:20:05 +00:00
|
|
|
connection.SetCapability(HasTokensCapability)
|
|
|
|
return
|
|
|
|
}
|
2019-11-26 21:10:09 +00:00
|
|
|
// This will close the connection by default and no tokens will be available.
|
|
|
|
// This usecase can be checked by the existing WaitForCapabilityOrClose() function using the HasTokensCapability
|
|
|
|
// If the connection closes without the HasTokensCapability then the error can be handled by whatever client needs it
|
2019-09-15 21:20:05 +00:00
|
|
|
log.Debugf("Failed to verify signed token batch")
|
|
|
|
}
|
2019-11-27 23:15:33 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// We are the server
|
|
|
|
var blinded []privacypass.BlindedToken
|
|
|
|
err := json.Unmarshal(connection.Expect(), &blinded)
|
|
|
|
if err == nil {
|
|
|
|
batchProof := tokenapp.TokenService.SignBlindedTokenBatch(blinded, tokenapp.Transcript())
|
|
|
|
log.Debugf(tokenapp.Transcript().OutputTranscriptToAudit())
|
|
|
|
data, _ := json.Marshal(batchProof)
|
|
|
|
connection.Send(data)
|
|
|
|
return
|
2019-09-15 21:20:05 +00:00
|
|
|
}
|
|
|
|
}
|