Crypto to f (#30)

* read and write ecdsa key into file

* file storage to F

* fix test

* add monad error

* header create

* store keys in json

* either -> try

* simplify config loading

* delete println

* add F to crypt

* comment fixes
This commit is contained in:
Dima 2018-02-06 13:52:13 +03:00 committed by GitHub
parent 3b7c2c3deb
commit 978634e450
4 changed files with 44 additions and 40 deletions

View File

@ -24,10 +24,10 @@ package fluence.crypto.cipher
* @tparam P The type of plain text, input
* @tparam C The type of cipher text, output
*/
trait Crypt[P, C] {
trait Crypt[F[_], P, C] {
def encrypt(plainText: P): C
def encrypt(plainText: P): F[C]
def decrypt(cipherText: C): P
def decrypt(cipherText: C): F[P]
}

View File

@ -17,7 +17,8 @@
package fluence.crypto.cipher
import scala.annotation.tailrec
import cats.Monad
import cats.syntax.functor._
import scala.collection.Searching.{ Found, InsertionPoint, SearchResult }
import scala.math.Ordering
@ -35,7 +36,7 @@ import scala.math.Ordering
*/
object CryptoSearching {
class CryptoSearchImpl[A](coll: IndexedSeq[A]) {
class CryptoSearchImpl[F[_], A](coll: IndexedSeq[A])(implicit F: Monad[F]) {
/**
* Searches the specified indexedSeq for the search element using the binary search algorithm.
@ -49,28 +50,26 @@ object CryptoSearching {
* sequence. A `InsertionPoint` value containing the index where the element would be inserted if
* the search element is not found in the sequence.
*/
final def binarySearch[B](searchElem: B)(implicit ordering: Ordering[B], decrypt: A B): SearchResult = {
binarySearchRec(searchElem, 0, coll.length, ordering, decrypt)
}
@tailrec
private def binarySearchRec[B](elem: B, from: Int, to: Int, ordering: Ordering[B], decrypt: A B): SearchResult = {
if (from == to) return InsertionPoint(from)
val idx = from + (to - from - 1) / 2
math.signum(ordering.compare(elem, decrypt(coll(idx)))) match {
case -1 binarySearchRec(elem, from, idx, ordering, decrypt)
case 1 binarySearchRec(elem, idx + 1, to, ordering, decrypt)
case _ Found(idx)
final def binarySearch[B](searchElem: B)(implicit ordering: Ordering[B], decrypt: A F[B]): F[SearchResult] = {
F.tailRecM((0, coll.length)) {
case (from, to) if from == to F.pure(Right(InsertionPoint(from)))
case (from, to)
val idx = from + (to - from - 1) / 2
decrypt(coll(idx)).map { d
math.signum(ordering.compare(searchElem, d)) match {
case -1 Left((from, idx))
case 1 Left((idx + 1, to))
case _ Right(Found(idx))
}
}
}
}
}
implicit def search[A](indexedSeq: IndexedSeq[A]): CryptoSearchImpl[A] =
implicit def search[F[_] : Monad, A](indexedSeq: IndexedSeq[A]): CryptoSearchImpl[F, A] =
new CryptoSearchImpl(indexedSeq)
implicit def search[A](array: Array[A]): CryptoSearchImpl[A] =
implicit def search[F[_] : Monad, A](array: Array[A]): CryptoSearchImpl[F, A] =
new CryptoSearchImpl(array)
}

View File

@ -19,29 +19,32 @@ package fluence.crypto.cipher
import java.nio.ByteBuffer
import cats.Applicative
import cats.syntax.applicative._
/**
* No operation implementation. Just convert the element to bytes back and forth without any cryptography.
*/
class NoOpCrypt[T](serializer: T Array[Byte], deserializer: Array[Byte] T) extends Crypt[T, Array[Byte]] {
class NoOpCrypt[F[_], T](serializer: T F[Array[Byte]], deserializer: Array[Byte] F[T]) extends Crypt[F, T, Array[Byte]] {
def encrypt(plainText: T): Array[Byte] = serializer(plainText)
def encrypt(plainText: T): F[Array[Byte]] = serializer(plainText)
def decrypt(cipherText: Array[Byte]): T = deserializer(cipherText)
def decrypt(cipherText: Array[Byte]): F[T] = deserializer(cipherText)
}
object NoOpCrypt {
val forString: NoOpCrypt[String] = apply[String](
serializer = _.getBytes,
deserializer = bytes new String(bytes))
def forString[F[_] : Applicative]: NoOpCrypt[F, String] = apply[F, String](
serializer = _.getBytes.pure[F],
deserializer = bytes new String(bytes).pure[F])
val forLong: NoOpCrypt[Long] = apply[Long](
serializer = ByteBuffer.allocate(java.lang.Long.BYTES).putLong(_).array(),
deserializer = bytes ByteBuffer.wrap(bytes).getLong()
def forLong[F[_] : Applicative]: NoOpCrypt[F, Long] = apply[F, Long](
serializer = ByteBuffer.allocate(java.lang.Long.BYTES).putLong(_).array().pure[F],
deserializer = bytes ByteBuffer.wrap(bytes).getLong().pure[F]
)
def apply[T](serializer: T Array[Byte], deserializer: Array[Byte] T): NoOpCrypt[T] =
def apply[F[_], T](serializer: T F[Array[Byte]], deserializer: Array[Byte] F[T]): NoOpCrypt[F, T] =
new NoOpCrypt(serializer, deserializer)
}

View File

@ -1,30 +1,32 @@
package fluence.crypto
import fluence.crypto.cipher.NoOpCrypt
import cats.instances.try_._
import org.scalatest.{ Matchers, WordSpec }
import scala.collection.Searching.{ Found, InsertionPoint }
import scala.util.Try
class CryptoSearchingSpec extends WordSpec with Matchers {
"search" should {
"correct search plainText key in encrypted data" in {
val crypt: NoOpCrypt[String] = NoOpCrypt.forString
val crypt: NoOpCrypt[Try, String] = NoOpCrypt.forString
val plainTextElements = Array("A", "B", "C", "D", "E")
val encryptedElements = plainTextElements.map(crypt.encrypt)
val encryptedElements = plainTextElements.map(t crypt.encrypt(t).get)
import fluence.crypto.cipher.CryptoSearching._
implicit val decryptFn: (Array[Byte]) String = crypt.decrypt
implicit val decryptFn: Array[Byte] Try[String] = crypt.decrypt
encryptedElements.binarySearch("B") shouldBe Found(1)
encryptedElements.binarySearch("D") shouldBe Found(3)
encryptedElements.binarySearch("E") shouldBe Found(4)
encryptedElements.binarySearch("B").get shouldBe Found(1)
encryptedElements.binarySearch("D").get shouldBe Found(3)
encryptedElements.binarySearch("E").get shouldBe Found(4)
encryptedElements.binarySearch("0") shouldBe InsertionPoint(0)
encryptedElements.binarySearch("BB") shouldBe InsertionPoint(2)
encryptedElements.binarySearch("ZZ") shouldBe InsertionPoint(5)
encryptedElements.binarySearch("0").get shouldBe InsertionPoint(0)
encryptedElements.binarySearch("BB").get shouldBe InsertionPoint(2)
encryptedElements.binarySearch("ZZ").get shouldBe InsertionPoint(5)
}
}