[#1093] Mailserver compatible with sync AND async keys (#1096)

This commit is contained in:
Adrià Cidre 2018-07-16 11:07:17 +02:00 committed by GitHub
parent bfbb02019f
commit 9ce96baf5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 90 additions and 21 deletions

View File

@ -83,10 +83,11 @@ type dbImpl interface {
// WMailServer whisper mailserver.
type WMailServer struct {
db dbImpl
w *whisper.Whisper
pow float64
filter *whisper.Filter
db dbImpl
w *whisper.Whisper
pow float64
symFilter *whisper.Filter
asymFilter *whisper.Filter
muLimiter sync.RWMutex
limiter *limiter
@ -154,7 +155,8 @@ func (s *WMailServer) setupLimiter(limit time.Duration) {
// setupRequestMessageDecryptor setup a Whisper filter to decrypt
// incoming Whisper requests.
func (s *WMailServer) setupRequestMessageDecryptor(config *params.WhisperConfig) error {
var filter whisper.Filter
s.symFilter = nil
s.asymFilter = nil
if config.MailServerPassword != "" {
keyID, err := s.w.AddSymKeyFromPassword(config.MailServerPassword)
@ -167,12 +169,12 @@ func (s *WMailServer) setupRequestMessageDecryptor(config *params.WhisperConfig)
return fmt.Errorf("save symmetric key: %v", err)
}
filter = whisper.Filter{KeySym: symKey}
} else if config.MailServerAsymKey != nil {
filter = whisper.Filter{KeyAsym: config.MailServerAsymKey}
s.symFilter = &whisper.Filter{KeySym: symKey}
}
s.filter = &filter
if config.MailServerAsymKey != nil {
s.asymFilter = &whisper.Filter{KeyAsym: config.MailServerAsymKey}
}
return nil
}
@ -357,13 +359,29 @@ func (s *WMailServer) sendHistoricMessageResponse(peer *whisper.Peer, request *w
return s.w.SendHistoricMessageResponse(peer, payload)
}
// openEnvelope tries to decrypt an envelope, first based on asymetric key (if
// provided) and second on the symetric key (if provided)
func (s *WMailServer) openEnvelope(request *whisper.Envelope) *whisper.ReceivedMessage {
if s.asymFilter != nil {
if d := request.Open(s.asymFilter); d != nil {
return d
}
}
if s.symFilter != nil {
if d := request.Open(s.symFilter); d != nil {
return d
}
}
return nil
}
// validateRequest runs different validations on the current request.
func (s *WMailServer) validateRequest(peerID []byte, request *whisper.Envelope) (bool, uint32, uint32, []byte, uint32, cursorType) {
if s.pow > 0.0 && request.PoW() < s.pow {
return false, 0, 0, nil, 0, nil
}
decrypted := request.Open(s.filter)
decrypted := s.openEnvelope(request)
if decrypted == nil {
log.Warn("Failed to decrypt p2p request")
return false, 0, 0, nil, 0, nil

View File

@ -39,6 +39,7 @@ const powRequirement = 0.00001
var keyID string
var seed = time.Now().Unix()
var testPayload = []byte("test payload")
type ServerTestParams struct {
topic whisper.TopicType
@ -191,25 +192,66 @@ func (s *MailserverSuite) TestSetupRequestMessageDecryptor() {
config = *s.config
s.NoError(config.ReadMailServerPasswordFile())
s.NoError(s.server.Init(s.shh, &config))
s.NotNil(s.server.filter.KeySym)
s.Nil(s.server.filter.KeyAsym)
s.Require().NotNil(s.server.symFilter)
s.NotNil(s.server.symFilter.KeySym)
s.Nil(s.server.asymFilter)
s.server.Close()
// AsymKey can also be used
config = *s.config
s.NoError(config.ReadMailServerAsymKeyFile())
s.NoError(s.server.Init(s.shh, &config))
s.Nil(s.server.filter.KeySym) // important: symmetric key should be nil
s.Equal(config.MailServerAsymKey, s.server.filter.KeyAsym)
s.Nil(s.server.symFilter) // important: symmetric filter should be nil
s.Require().NotNil(s.server.asymFilter)
s.Equal(config.MailServerAsymKey, s.server.asymFilter.KeyAsym)
s.server.Close()
// when both Password and AsymKey are set, Password has a preference
// when Password and AsymKey are set, both are supported
config = *s.config
s.NoError(config.ReadMailServerPasswordFile())
s.NoError(config.ReadMailServerAsymKeyFile())
s.NoError(s.server.Init(s.shh, &config))
s.NotNil(s.server.filter.KeySym)
s.Nil(s.server.filter.KeyAsym)
s.Require().NotNil(s.server.symFilter)
s.NotNil(s.server.symFilter.KeySym)
s.NotNil(s.server.asymFilter.KeyAsym)
s.server.Close()
}
func (s *MailserverSuite) TestOpenEnvelopeWithSymKey() {
// Setup the server with a sym key
config := *s.config
s.NoError(config.ReadMailServerPasswordFile())
s.NoError(s.server.Init(s.shh, &config))
// Prepare a valid envelope
s.Require().NotNil(s.server.symFilter)
symKey := s.server.symFilter.KeySym
env, err := generateEnvelopeWithKeys(time.Now(), symKey, nil)
s.Require().NoError(err)
// Test openEnvelope with a valid envelope
d := s.server.openEnvelope(env)
s.NotNil(d)
s.Equal(testPayload, d.Payload)
s.server.Close()
}
func (s *MailserverSuite) TestOpenEnvelopeWithAsymKey() {
// Setup the server with an asymetric key
config := *s.config
s.NoError(config.ReadMailServerAsymKeyFile())
s.NoError(s.server.Init(s.shh, &config))
// Prepare a valid envelope
s.Require().NotNil(s.server.asymFilter)
pubKey := s.server.asymFilter.KeyAsym.PublicKey
env, err := generateEnvelopeWithKeys(time.Now(), nil, &pubKey)
s.Require().NoError(err)
// Test openEnvelope with a valid asymetric key
d := s.server.openEnvelope(env)
s.NotNil(d)
s.Equal(testPayload, d.Payload)
s.server.Close()
}
@ -538,16 +580,20 @@ func (s *MailserverSuite) createRequest(p *ServerTestParams) *whisper.Envelope {
return env
}
func generateEnvelope(sentTime time.Time) (*whisper.Envelope, error) {
h := crypto.Keccak256Hash([]byte("test sample data"))
func generateEnvelopeWithKeys(sentTime time.Time, keySym []byte, keyAsym *ecdsa.PublicKey) (*whisper.Envelope, error) {
params := &whisper.MessageParams{
KeySym: h[:],
Topic: whisper.TopicType{0x1F, 0x7E, 0xA1, 0x7F},
Payload: []byte("test payload"),
Payload: testPayload,
PoW: powRequirement,
WorkTime: 2,
}
if len(keySym) > 0 {
params.KeySym = keySym
} else if keyAsym != nil {
params.Dst = keyAsym
}
msg, err := whisper.NewSentMessage(params)
if err != nil {
return nil, fmt.Errorf("failed to create new message with seed %d: %s", seed, err)
@ -559,3 +605,8 @@ func generateEnvelope(sentTime time.Time) (*whisper.Envelope, error) {
return env, nil
}
func generateEnvelope(sentTime time.Time) (*whisper.Envelope, error) {
h := crypto.Keccak256Hash([]byte("test sample data"))
return generateEnvelopeWithKeys(sentTime, h[:], nil)
}