wip on signing queries

pull/24/head
Zlatin Balevsky 2019-11-02 18:34:13 +00:00
parent 27aad9d75d
commit 1ce410e943
5 changed files with 53 additions and 4 deletions

View File

@ -8,7 +8,11 @@ import com.muwire.core.search.SearchEvent
import com.muwire.core.search.UIResultBatchEvent
import com.muwire.core.search.UIResultEvent
import net.i2p.crypto.DSAEngine
import net.i2p.data.Base64
import net.i2p.data.Signature
import java.nio.charset.StandardCharsets
import com.googlecode.lanterna.gui2.TextGUIThread
import com.googlecode.lanterna.gui2.table.TableModel
@ -40,20 +44,27 @@ class SearchModel {
}
def searchEvent
byte [] payload
if (hashSearch) {
searchEvent = new SearchEvent(searchHash : root, uuid : UUID.randomUUID(), oobInfohash : true, compressedResults : true)
payload = root
} else {
def replaced = query.toLowerCase().trim().replaceAll(SplitPattern.SPLIT_PATTERN, " ")
def terms = replaced.split(" ")
def nonEmpty = []
terms.each { if (it.length() > 0) nonEmpty << it }
payload = String.join(" ", nonEmpty).getBytes(StandardCharsets.UTF_8)
searchEvent = new SearchEvent(searchTerms : nonEmpty, uuid : UUID.randomUUID(), oobInfohash: true,
searchComments : core.muOptions.searchComments, compressedResults : true)
}
boolean firstHop = core.muOptions.allowUntrusted || core.muOptions.searchExtraHop
Signature sig = DSAEngine.getInstance().sign(payload, core.spk)
core.eventBus.publish(new QueryEvent(searchEvent : searchEvent, firstHop : firstHop,
replyTo: core.me.destination, receivedOn: core.me.destination,
originator : core.me))
originator : core.me, sig: sig.data))
}
void unregister() {

View File

@ -103,6 +103,8 @@ public class Core {
private final Router router
final AtomicBoolean shutdown = new AtomicBoolean()
final SigningPrivateKey spk
public Core(MuWireSettings props, File home, String myVersion) {
this.home = home
@ -180,7 +182,7 @@ public class Core {
i2pSession = socketManager.getSession()
def destination = new Destination()
def spk = new SigningPrivateKey(Constants.SIG_TYPE)
spk = new SigningPrivateKey(Constants.SIG_TYPE)
keyDat.withInputStream {
destination.readBytes(it)
def privateKey = new PrivateKey()

View File

@ -1,5 +1,6 @@
package com.muwire.core.connection
import java.nio.charset.StandardCharsets
import java.util.concurrent.BlockingQueue
import java.util.concurrent.CountDownLatch
import java.util.concurrent.ExecutorService
@ -10,6 +11,7 @@ import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicBoolean
import java.util.logging.Level
import com.muwire.core.Constants
import com.muwire.core.EventBus
import com.muwire.core.MuWireSettings
import com.muwire.core.Persona
@ -21,8 +23,10 @@ import com.muwire.core.trust.TrustLevel
import com.muwire.core.trust.TrustService
import groovy.util.logging.Log
import net.i2p.crypto.DSAEngine
import net.i2p.data.Base64
import net.i2p.data.Destination
import net.i2p.data.Signature
@Log
abstract class Connection implements Closeable {
@ -147,6 +151,8 @@ abstract class Connection implements Closeable {
query.replyTo = e.replyTo.toBase64()
if (e.originator != null)
query.originator = e.originator.toBase64()
if (e.sig != null)
query.sig = Base64.encode(e.sig)
messages.put(query)
}
@ -225,6 +231,24 @@ abstract class Connection implements Closeable {
boolean compressedResults = false
if (search.compressedResults != null)
compressedResults = search.compressedResults
byte[] sig = null
// TODO: make this mandatory at some point
if (search.sig != null) {
sig = Base64.decode(search.sig)
byte [] payload
if (infohash != null)
payload = infohash
else
payload = String.join(" ",search.keywords).getBytes(StandardCharsets.UTF_8)
def spk = originator.destination.getSigningPublicKey()
def signature = new Signature(Constants.SIG_TYPE, sig)
if (!DSAEngine.getInstance().verifySig(signature, payload, spk)) {
log.info("signature didn't match keywords")
return
} else
log.info("query signature verified")
} else
log.info("no signature in query")
SearchEvent searchEvent = new SearchEvent(searchTerms : search.keywords,
searchHash : infohash,
@ -236,7 +260,8 @@ abstract class Connection implements Closeable {
replyTo : replyTo,
originator : originator,
receivedOn : endpoint.destination,
firstHop : search.firstHop )
firstHop : search.firstHop,
sig : sig )
eventBus.publish(event)
}

View File

@ -12,6 +12,7 @@ class QueryEvent extends Event {
Destination replyTo
Persona originator
Destination receivedOn
byte[] sig
String toString() {
"searchEvent: $searchEvent firstHop:$firstHop, replyTo:${replyTo.toBase32()}" +

View File

@ -7,7 +7,11 @@ import griffon.core.mvc.MVCGroup
import griffon.core.mvc.MVCGroupConfiguration
import griffon.inject.MVCMember
import griffon.metadata.ArtifactProviderFor
import net.i2p.crypto.DSAEngine
import net.i2p.data.Base64
import net.i2p.data.Signature
import java.nio.charset.StandardCharsets
import javax.annotation.Nonnull
import javax.inject.Inject
@ -77,21 +81,27 @@ class MainFrameController {
}
def searchEvent
byte [] payload
if (hashSearch) {
searchEvent = new SearchEvent(searchHash : root, uuid : uuid, oobInfohash: true, compressedResults : true)
payload = root
} else {
// this can be improved a lot
def replaced = search.toLowerCase().trim().replaceAll(SplitPattern.SPLIT_PATTERN, " ")
def terms = replaced.split(" ")
def nonEmpty = []
terms.each { if (it.length() > 0) nonEmpty << it }
payload = String.join(" ",nonEmpty).getBytes(StandardCharsets.UTF_8)
searchEvent = new SearchEvent(searchTerms : nonEmpty, uuid : uuid, oobInfohash: true,
searchComments : core.muOptions.searchComments, compressedResults : true)
}
boolean firstHop = core.muOptions.allowUntrusted || core.muOptions.searchExtraHop
Signature sig = DSAEngine.getInstance().sign(payload, core.spk)
core.eventBus.publish(new QueryEvent(searchEvent : searchEvent, firstHop : firstHop,
replyTo: core.me.destination, receivedOn: core.me.destination,
originator : core.me))
originator : core.me, sig : sig.data))
}
void search(String infoHash, String tabTitle) {