wip on signing queries
This commit is contained in:
@@ -8,7 +8,11 @@ import com.muwire.core.search.SearchEvent
|
|||||||
import com.muwire.core.search.UIResultBatchEvent
|
import com.muwire.core.search.UIResultBatchEvent
|
||||||
import com.muwire.core.search.UIResultEvent
|
import com.muwire.core.search.UIResultEvent
|
||||||
|
|
||||||
|
import net.i2p.crypto.DSAEngine
|
||||||
import net.i2p.data.Base64
|
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.TextGUIThread
|
||||||
import com.googlecode.lanterna.gui2.table.TableModel
|
import com.googlecode.lanterna.gui2.table.TableModel
|
||||||
@@ -40,20 +44,27 @@ class SearchModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def searchEvent
|
def searchEvent
|
||||||
|
byte [] payload
|
||||||
if (hashSearch) {
|
if (hashSearch) {
|
||||||
searchEvent = new SearchEvent(searchHash : root, uuid : UUID.randomUUID(), oobInfohash : true, compressedResults : true)
|
searchEvent = new SearchEvent(searchHash : root, uuid : UUID.randomUUID(), oobInfohash : true, compressedResults : true)
|
||||||
|
payload = root
|
||||||
} else {
|
} else {
|
||||||
def replaced = query.toLowerCase().trim().replaceAll(SplitPattern.SPLIT_PATTERN, " ")
|
def replaced = query.toLowerCase().trim().replaceAll(SplitPattern.SPLIT_PATTERN, " ")
|
||||||
def terms = replaced.split(" ")
|
def terms = replaced.split(" ")
|
||||||
def nonEmpty = []
|
def nonEmpty = []
|
||||||
terms.each { if (it.length() > 0) nonEmpty << it }
|
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,
|
searchEvent = new SearchEvent(searchTerms : nonEmpty, uuid : UUID.randomUUID(), oobInfohash: true,
|
||||||
searchComments : core.muOptions.searchComments, compressedResults : true)
|
searchComments : core.muOptions.searchComments, compressedResults : true)
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean firstHop = core.muOptions.allowUntrusted || core.muOptions.searchExtraHop
|
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,
|
core.eventBus.publish(new QueryEvent(searchEvent : searchEvent, firstHop : firstHop,
|
||||||
replyTo: core.me.destination, receivedOn: core.me.destination,
|
replyTo: core.me.destination, receivedOn: core.me.destination,
|
||||||
originator : core.me))
|
originator : core.me, sig: sig.data))
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregister() {
|
void unregister() {
|
||||||
|
@@ -104,6 +104,8 @@ public class Core {
|
|||||||
|
|
||||||
final AtomicBoolean shutdown = new AtomicBoolean()
|
final AtomicBoolean shutdown = new AtomicBoolean()
|
||||||
|
|
||||||
|
final SigningPrivateKey spk
|
||||||
|
|
||||||
public Core(MuWireSettings props, File home, String myVersion) {
|
public Core(MuWireSettings props, File home, String myVersion) {
|
||||||
this.home = home
|
this.home = home
|
||||||
this.muOptions = props
|
this.muOptions = props
|
||||||
@@ -180,7 +182,7 @@ public class Core {
|
|||||||
i2pSession = socketManager.getSession()
|
i2pSession = socketManager.getSession()
|
||||||
|
|
||||||
def destination = new Destination()
|
def destination = new Destination()
|
||||||
def spk = new SigningPrivateKey(Constants.SIG_TYPE)
|
spk = new SigningPrivateKey(Constants.SIG_TYPE)
|
||||||
keyDat.withInputStream {
|
keyDat.withInputStream {
|
||||||
destination.readBytes(it)
|
destination.readBytes(it)
|
||||||
def privateKey = new PrivateKey()
|
def privateKey = new PrivateKey()
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
package com.muwire.core.connection
|
package com.muwire.core.connection
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
import java.util.concurrent.BlockingQueue
|
import java.util.concurrent.BlockingQueue
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
import java.util.concurrent.ExecutorService
|
import java.util.concurrent.ExecutorService
|
||||||
@@ -10,6 +11,7 @@ import java.util.concurrent.TimeUnit
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
|
|
||||||
|
import com.muwire.core.Constants
|
||||||
import com.muwire.core.EventBus
|
import com.muwire.core.EventBus
|
||||||
import com.muwire.core.MuWireSettings
|
import com.muwire.core.MuWireSettings
|
||||||
import com.muwire.core.Persona
|
import com.muwire.core.Persona
|
||||||
@@ -21,8 +23,10 @@ import com.muwire.core.trust.TrustLevel
|
|||||||
import com.muwire.core.trust.TrustService
|
import com.muwire.core.trust.TrustService
|
||||||
|
|
||||||
import groovy.util.logging.Log
|
import groovy.util.logging.Log
|
||||||
|
import net.i2p.crypto.DSAEngine
|
||||||
import net.i2p.data.Base64
|
import net.i2p.data.Base64
|
||||||
import net.i2p.data.Destination
|
import net.i2p.data.Destination
|
||||||
|
import net.i2p.data.Signature
|
||||||
|
|
||||||
@Log
|
@Log
|
||||||
abstract class Connection implements Closeable {
|
abstract class Connection implements Closeable {
|
||||||
@@ -147,6 +151,8 @@ abstract class Connection implements Closeable {
|
|||||||
query.replyTo = e.replyTo.toBase64()
|
query.replyTo = e.replyTo.toBase64()
|
||||||
if (e.originator != null)
|
if (e.originator != null)
|
||||||
query.originator = e.originator.toBase64()
|
query.originator = e.originator.toBase64()
|
||||||
|
if (e.sig != null)
|
||||||
|
query.sig = Base64.encode(e.sig)
|
||||||
messages.put(query)
|
messages.put(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,6 +231,24 @@ abstract class Connection implements Closeable {
|
|||||||
boolean compressedResults = false
|
boolean compressedResults = false
|
||||||
if (search.compressedResults != null)
|
if (search.compressedResults != null)
|
||||||
compressedResults = search.compressedResults
|
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,
|
SearchEvent searchEvent = new SearchEvent(searchTerms : search.keywords,
|
||||||
searchHash : infohash,
|
searchHash : infohash,
|
||||||
@@ -236,7 +260,8 @@ abstract class Connection implements Closeable {
|
|||||||
replyTo : replyTo,
|
replyTo : replyTo,
|
||||||
originator : originator,
|
originator : originator,
|
||||||
receivedOn : endpoint.destination,
|
receivedOn : endpoint.destination,
|
||||||
firstHop : search.firstHop )
|
firstHop : search.firstHop,
|
||||||
|
sig : sig )
|
||||||
eventBus.publish(event)
|
eventBus.publish(event)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,7 @@ class QueryEvent extends Event {
|
|||||||
Destination replyTo
|
Destination replyTo
|
||||||
Persona originator
|
Persona originator
|
||||||
Destination receivedOn
|
Destination receivedOn
|
||||||
|
byte[] sig
|
||||||
|
|
||||||
String toString() {
|
String toString() {
|
||||||
"searchEvent: $searchEvent firstHop:$firstHop, replyTo:${replyTo.toBase32()}" +
|
"searchEvent: $searchEvent firstHop:$firstHop, replyTo:${replyTo.toBase32()}" +
|
||||||
|
@@ -7,7 +7,11 @@ import griffon.core.mvc.MVCGroup
|
|||||||
import griffon.core.mvc.MVCGroupConfiguration
|
import griffon.core.mvc.MVCGroupConfiguration
|
||||||
import griffon.inject.MVCMember
|
import griffon.inject.MVCMember
|
||||||
import griffon.metadata.ArtifactProviderFor
|
import griffon.metadata.ArtifactProviderFor
|
||||||
|
import net.i2p.crypto.DSAEngine
|
||||||
import net.i2p.data.Base64
|
import net.i2p.data.Base64
|
||||||
|
import net.i2p.data.Signature
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
import javax.annotation.Nonnull
|
import javax.annotation.Nonnull
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -77,21 +81,27 @@ class MainFrameController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def searchEvent
|
def searchEvent
|
||||||
|
byte [] payload
|
||||||
if (hashSearch) {
|
if (hashSearch) {
|
||||||
searchEvent = new SearchEvent(searchHash : root, uuid : uuid, oobInfohash: true, compressedResults : true)
|
searchEvent = new SearchEvent(searchHash : root, uuid : uuid, oobInfohash: true, compressedResults : true)
|
||||||
|
payload = root
|
||||||
} else {
|
} else {
|
||||||
// this can be improved a lot
|
// this can be improved a lot
|
||||||
def replaced = search.toLowerCase().trim().replaceAll(SplitPattern.SPLIT_PATTERN, " ")
|
def replaced = search.toLowerCase().trim().replaceAll(SplitPattern.SPLIT_PATTERN, " ")
|
||||||
def terms = replaced.split(" ")
|
def terms = replaced.split(" ")
|
||||||
def nonEmpty = []
|
def nonEmpty = []
|
||||||
terms.each { if (it.length() > 0) nonEmpty << it }
|
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,
|
searchEvent = new SearchEvent(searchTerms : nonEmpty, uuid : uuid, oobInfohash: true,
|
||||||
searchComments : core.muOptions.searchComments, compressedResults : true)
|
searchComments : core.muOptions.searchComments, compressedResults : true)
|
||||||
}
|
}
|
||||||
boolean firstHop = core.muOptions.allowUntrusted || core.muOptions.searchExtraHop
|
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,
|
core.eventBus.publish(new QueryEvent(searchEvent : searchEvent, firstHop : firstHop,
|
||||||
replyTo: core.me.destination, receivedOn: core.me.destination,
|
replyTo: core.me.destination, receivedOn: core.me.destination,
|
||||||
originator : core.me))
|
originator : core.me, sig : sig.data))
|
||||||
}
|
}
|
||||||
|
|
||||||
void search(String infoHash, String tabTitle) {
|
void search(String infoHash, String tabTitle) {
|
||||||
|
Reference in New Issue
Block a user