eddsa #1
14 changed files with 204 additions and 177 deletions
|
|
@ -3,11 +3,11 @@ package gs.crypto.v0
|
||||||
import java.{util => ju}
|
import java.{util => ju}
|
||||||
|
|
||||||
/** Implementation of [[Decoder]] for Base64 strings.
|
/** Implementation of [[Decoder]] for Base64 strings.
|
||||||
*
|
*
|
||||||
* Supports base64-url decoding as well.
|
* Supports base64-url decoding as well.
|
||||||
*/
|
*/
|
||||||
object Base64Decoder extends Decoder[B64]:
|
object Base64Decoder extends Decoder[B64]:
|
||||||
private lazy val d: ju.Base64.Decoder = ju.Base64.getDecoder()
|
private lazy val d: ju.Base64.Decoder = ju.Base64.getDecoder()
|
||||||
private lazy val du: ju.Base64.Decoder = ju.Base64.getUrlDecoder()
|
private lazy val du: ju.Base64.Decoder = ju.Base64.getUrlDecoder()
|
||||||
|
|
||||||
/** @inheritDocs
|
/** @inheritDocs
|
||||||
|
|
@ -25,11 +25,12 @@ object Base64Decoder extends Decoder[B64]:
|
||||||
def decodeUnsafe(input: String): Array[Byte] =
|
def decodeUnsafe(input: String): Array[Byte] =
|
||||||
d.decode(input)
|
d.decode(input)
|
||||||
|
|
||||||
/**
|
/** Decode the base64-url encoded input.
|
||||||
* Decode the base64-url encoded input.
|
*
|
||||||
*
|
* @param input
|
||||||
* @param input The base64-url encoded data.
|
* The base64-url encoded data.
|
||||||
* @return The decoded bytes.
|
* @return
|
||||||
*/
|
* The decoded bytes.
|
||||||
|
*/
|
||||||
def decodeUrl(input: B64Url): Array[Byte] =
|
def decodeUrl(input: B64Url): Array[Byte] =
|
||||||
du.decode(input.data)
|
du.decode(input.data)
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ import java.nio.charset.StandardCharsets
|
||||||
import java.util.Base64
|
import java.util.Base64
|
||||||
|
|
||||||
/** Implementation of [[Encoder]] for Base64.
|
/** Implementation of [[Encoder]] for Base64.
|
||||||
*
|
*
|
||||||
* Supports base64-url encoding as well.
|
* Supports base64-url encoding as well.
|
||||||
*/
|
*/
|
||||||
object Base64Encoder extends Encoder[B64]:
|
object Base64Encoder extends Encoder[B64]:
|
||||||
private lazy val e: Base64.Encoder = Base64.getEncoder()
|
private lazy val e: Base64.Encoder = Base64.getEncoder()
|
||||||
private lazy val eu: Base64.Encoder = Base64.getUrlEncoder()
|
private lazy val eu: Base64.Encoder = Base64.getUrlEncoder()
|
||||||
|
|
||||||
/** @inheritDocs
|
/** @inheritDocs
|
||||||
|
|
@ -25,22 +25,25 @@ object Base64Encoder extends Encoder[B64]:
|
||||||
): B64 =
|
): B64 =
|
||||||
encode(input.getBytes(charset))
|
encode(input.getBytes(charset))
|
||||||
|
|
||||||
/**
|
/** Encode the given bytes using base64-url.
|
||||||
* Encode the given bytes using base64-url.
|
*
|
||||||
*
|
* @param input
|
||||||
* @param input The input data.
|
* The input data.
|
||||||
* @return The base64-url-encoded string.
|
* @return
|
||||||
*/
|
* The base64-url-encoded string.
|
||||||
|
*/
|
||||||
def encodeUrl(input: Array[Byte]): B64Url =
|
def encodeUrl(input: Array[Byte]): B64Url =
|
||||||
B64Url(eu.encodeToString(input))
|
B64Url(eu.encodeToString(input))
|
||||||
|
|
||||||
/**
|
/** Encode the given bytes using base64-url.
|
||||||
* Encode the given bytes using base64-url.
|
*
|
||||||
*
|
* @param input
|
||||||
* @param input The input data.
|
* The input data.
|
||||||
* @param charset The character set of the input data.
|
* @param charset
|
||||||
* @return The base64-url-encoded string.
|
* The character set of the input data.
|
||||||
*/
|
* @return
|
||||||
|
* The base64-url-encoded string.
|
||||||
|
*/
|
||||||
def encodeUrl(
|
def encodeUrl(
|
||||||
input: String,
|
input: String,
|
||||||
charset: Charset = StandardCharsets.UTF_8
|
charset: Charset = StandardCharsets.UTF_8
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,30 @@
|
||||||
package gs.crypto.v0
|
package gs.crypto.v0
|
||||||
|
|
||||||
/**
|
/** Base implementation for [[KeyLoader]] that provides standard parsing
|
||||||
* Base implementation for [[KeyLoader]] that provides standard parsing
|
|
||||||
* functionality.
|
* functionality.
|
||||||
*/
|
*/
|
||||||
abstract class BaseKeyLoader[F[_]] extends KeyLoader[F]:
|
abstract class BaseKeyLoader[F[_]] extends KeyLoader[F]:
|
||||||
/**
|
/** @return
|
||||||
* @return The key loader configuration.
|
* The key loader configuration.
|
||||||
*/
|
*/
|
||||||
def config: BaseKeyLoader.Config
|
def config: BaseKeyLoader.Config
|
||||||
|
|
||||||
protected def prepareKey(base: String): Either[KeyLoadError, Array[Byte]] =
|
protected def prepareKey(base: String): Either[KeyLoadError, Array[Byte]] =
|
||||||
scala.util.Try {
|
scala.util
|
||||||
config.decoder.decode(trim(collapse(unwrap(base))))
|
.Try {
|
||||||
}.toEither.left.map(_ => KeyLoadError.DecodingFailure(config.encodingName))
|
config.decoder.decode(trim(collapse(unwrap(base))))
|
||||||
|
}
|
||||||
|
.toEither
|
||||||
|
.left
|
||||||
|
.map(_ => KeyLoadError.DecodingFailure(config.encodingName))
|
||||||
|
|
||||||
private def unwrap(base: String): String =
|
private def unwrap(base: String): String =
|
||||||
config.wrappers.foldLeft(base) { (acc, w) => acc.replace(w, "") }
|
config.wrappers.foldLeft(base) {
|
||||||
|
(
|
||||||
|
acc,
|
||||||
|
w
|
||||||
|
) => acc.replace(w, "")
|
||||||
|
}
|
||||||
|
|
||||||
private def collapse(base: String): String =
|
private def collapse(base: String): String =
|
||||||
if config.shouldCollapse then base.replace("\n", "") else base
|
if config.shouldCollapse then base.replace("\n", "") else base
|
||||||
|
|
@ -26,15 +34,19 @@ abstract class BaseKeyLoader[F[_]] extends KeyLoader[F]:
|
||||||
|
|
||||||
object BaseKeyLoader:
|
object BaseKeyLoader:
|
||||||
|
|
||||||
/**
|
/** Configuration for loading keys.
|
||||||
* Configuration for loading keys.
|
*
|
||||||
*
|
* @param wrappers
|
||||||
* @param wrappers Values that wrap keys and must be removed.
|
* Values that wrap keys and must be removed.
|
||||||
* @param shouldCollapse Whether newlines should be collapsed.
|
* @param shouldCollapse
|
||||||
* @param shouldTrim Whether the string data should be trimmed.
|
* Whether newlines should be collapsed.
|
||||||
* @param encodingName The name of the encoding.
|
* @param shouldTrim
|
||||||
* @param decoder The decoder to be used on the pre-processed input.
|
* Whether the string data should be trimmed.
|
||||||
*/
|
* @param encodingName
|
||||||
|
* The name of the encoding.
|
||||||
|
* @param decoder
|
||||||
|
* The decoder to be used on the pre-processed input.
|
||||||
|
*/
|
||||||
case class Config(
|
case class Config(
|
||||||
wrappers: List[String],
|
wrappers: List[String],
|
||||||
shouldCollapse: Boolean,
|
shouldCollapse: Boolean,
|
||||||
|
|
@ -43,39 +55,33 @@ object BaseKeyLoader:
|
||||||
decoder: Decoder[String]
|
decoder: Decoder[String]
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/** Default configuration values that work in most cases.
|
||||||
* Default configuration values that work in most cases.
|
*/
|
||||||
*/
|
|
||||||
object Defaults:
|
object Defaults:
|
||||||
|
|
||||||
/**
|
/** By default, generic begin/end public/private key wrappers are included.
|
||||||
* By default, generic begin/end public/private key wrappers are included.
|
*/
|
||||||
*/
|
|
||||||
val Wrappers: List[String] = List(
|
val Wrappers: List[String] = List(
|
||||||
"-----BEGIN PUBLIC KEY-----",
|
"-----BEGIN PUBLIC KEY-----",
|
||||||
"-----END PUBLIC KEY-----",
|
"-----END PUBLIC KEY-----",
|
||||||
"-----BEGIN PRIVATE KEY-----",
|
"-----BEGIN PRIVATE KEY-----",
|
||||||
"-----END PRIVATE KEY-----",
|
"-----END PRIVATE KEY-----"
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/** By default, stringified key data has newlines removed.
|
||||||
* By default, stringified key data has newlines removed.
|
*/
|
||||||
*/
|
|
||||||
val ShouldCollapse: Boolean = true
|
val ShouldCollapse: Boolean = true
|
||||||
|
|
||||||
/**
|
/** By default, stringified key data is trimmed.
|
||||||
* By default, stringified key data is trimmed.
|
*/
|
||||||
*/
|
|
||||||
val ShouldTrim: Boolean = true
|
val ShouldTrim: Boolean = true
|
||||||
|
|
||||||
/**
|
/** The default encoding name is 'base64'.
|
||||||
* The default encoding name is 'base64'.
|
*/
|
||||||
*/
|
|
||||||
val EncodingName: String = "base64"
|
val EncodingName: String = "base64"
|
||||||
|
|
||||||
/**
|
/** The default configuration handles standard wrapped, base64-encoded keys.
|
||||||
* The default configuration handles standard wrapped, base64-encoded keys.
|
*/
|
||||||
*/
|
|
||||||
val Config: BaseKeyLoader.Config = BaseKeyLoader.Config(
|
val Config: BaseKeyLoader.Config = BaseKeyLoader.Config(
|
||||||
wrappers = Wrappers,
|
wrappers = Wrappers,
|
||||||
shouldCollapse = ShouldCollapse,
|
shouldCollapse = ShouldCollapse,
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,28 @@
|
||||||
package gs.crypto.v0
|
package gs.crypto.v0
|
||||||
|
|
||||||
import cats.syntax.all.*
|
|
||||||
import cats.effect.Sync
|
import cats.effect.Sync
|
||||||
|
import cats.syntax.all.*
|
||||||
|
import java.nio.charset.Charset
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.charset.Charset
|
|
||||||
|
|
||||||
/**
|
/** Implementation of [[KeyLoader]] that loads keys from encoded string files.
|
||||||
* Implementation of [[KeyLoader]] that loads keys from encoded string files.
|
|
||||||
*
|
*
|
||||||
* @param config The key loader configuration.
|
* @param config
|
||||||
* @param charset The expected character set for the loaded file.
|
* The key loader configuration.
|
||||||
|
* @param charset
|
||||||
|
* The expected character set for the loaded file.
|
||||||
*/
|
*/
|
||||||
class FileKeyLoader[F[_]: Sync](
|
class FileKeyLoader[F[_]: Sync](
|
||||||
val config: BaseKeyLoader.Config,
|
val config: BaseKeyLoader.Config,
|
||||||
val charset: Charset
|
val charset: Charset
|
||||||
) extends BaseKeyLoader[F]:
|
) extends BaseKeyLoader[F]:
|
||||||
|
|
||||||
/** @inheritDocs */
|
/** @inheritDocs
|
||||||
|
*/
|
||||||
override def loadKey(
|
override def loadKey(
|
||||||
location: String
|
location: String
|
||||||
): F[Either[KeyLoadError, Array[Byte]]] =
|
): F[Either[KeyLoadError, Array[Byte]]] =
|
||||||
val p = Path.of(location)
|
val p = Path.of(location)
|
||||||
Sync[F].delay(Files.isRegularFile(p)).flatMap {
|
Sync[F].delay(Files.isRegularFile(p)).flatMap {
|
||||||
case false =>
|
case false =>
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,11 @@ sealed trait KeyLoadError
|
||||||
|
|
||||||
object KeyLoadError:
|
object KeyLoadError:
|
||||||
|
|
||||||
case class PathNotRegularFile(path: Path, location: String) extends KeyLoadError
|
case class PathNotRegularFile(
|
||||||
|
path: Path,
|
||||||
|
location: String
|
||||||
|
) extends KeyLoadError
|
||||||
|
|
||||||
case class DecodingFailure(encodedFormat: String) extends KeyLoadError
|
case class DecodingFailure(encodedFormat: String) extends KeyLoadError
|
||||||
|
|
||||||
end KeyLoadError
|
end KeyLoadError
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,16 @@ import cats.effect.Sync
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
/**
|
/** Interface for loading keys (e.g. public/private keys) into memory.
|
||||||
* Interface for loading keys (e.g. public/private keys) into memory.
|
*/
|
||||||
*/
|
|
||||||
trait KeyLoader[F[_]]:
|
trait KeyLoader[F[_]]:
|
||||||
/**
|
/** Load the key from the given location.
|
||||||
* Load the key from the given location.
|
*
|
||||||
*
|
* @param location
|
||||||
* @param location The location of the key.
|
* The location of the key.
|
||||||
* @return The loaded key.
|
* @return
|
||||||
*/
|
* The loaded key.
|
||||||
|
*/
|
||||||
def loadKey(location: String): F[Either[KeyLoadError, Array[Byte]]]
|
def loadKey(location: String): F[Either[KeyLoadError, Array[Byte]]]
|
||||||
|
|
||||||
object KeyLoader:
|
object KeyLoader:
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,26 @@
|
||||||
package gs.crypto.v0
|
package gs.crypto.v0
|
||||||
|
|
||||||
import cats.effect.Sync
|
|
||||||
import cats.effect.Resource
|
import cats.effect.Resource
|
||||||
|
import cats.effect.Sync
|
||||||
import scala.io.Source
|
import scala.io.Source
|
||||||
|
|
||||||
/**
|
/** Implementation of [[KeyLoader]] that loads keys from encoded string files
|
||||||
* Implementation of [[KeyLoader]] that loads keys from encoded string files
|
|
||||||
* that exist as project resources.
|
* that exist as project resources.
|
||||||
*
|
*
|
||||||
* @param config The key loader configuration.
|
* @param config
|
||||||
|
* The key loader configuration.
|
||||||
*/
|
*/
|
||||||
class ResourceKeyLoader[F[_]: Sync](
|
class ResourceKeyLoader[F[_]: Sync](
|
||||||
val config: BaseKeyLoader.Config
|
val config: BaseKeyLoader.Config
|
||||||
) extends BaseKeyLoader[F]:
|
) extends BaseKeyLoader[F]:
|
||||||
|
|
||||||
/** @inheritDocs */
|
/** @inheritDocs
|
||||||
|
*/
|
||||||
override def loadKey(
|
override def loadKey(
|
||||||
location: String
|
location: String
|
||||||
): F[Either[KeyLoadError, Array[Byte]]] =
|
): F[Either[KeyLoadError, Array[Byte]]] =
|
||||||
Resource
|
Resource
|
||||||
.make(Sync[F].delay(Source.fromResource(location)))(source =>
|
.make(Sync[F].delay(Source.fromResource(location)))(source =>
|
||||||
Sync[F].delay(source.close())
|
Sync[F].delay(source.close())
|
||||||
)
|
)
|
||||||
.use { source =>
|
.use(source => Sync[F].delay(prepareKey(source.getLines().mkString)))
|
||||||
Sync[F].delay(prepareKey(source.getLines().mkString))
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,50 +1,51 @@
|
||||||
package gs.crypto.v0
|
package gs.crypto.v0
|
||||||
|
|
||||||
/**
|
/** Represents a cryptographic signature. Opaque type for an array of bytes.
|
||||||
* Represents a cryptographic signature. Opaque type for an array of bytes.
|
|
||||||
*/
|
*/
|
||||||
opaque type Signature = Array[Byte]
|
opaque type Signature = Array[Byte]
|
||||||
|
|
||||||
object Signature:
|
object Signature:
|
||||||
|
|
||||||
/**
|
/** Instantiate a new signature from the given byte array.
|
||||||
* Instantiate a new signature from the given byte array.
|
*
|
||||||
*
|
* @param value
|
||||||
* @param value The signature value.
|
* The signature value.
|
||||||
* @return The signature bytes.
|
* @return
|
||||||
*/
|
* The signature bytes.
|
||||||
|
*/
|
||||||
def apply(value: Array[Byte]): Signature = value
|
def apply(value: Array[Byte]): Signature = value
|
||||||
|
|
||||||
/**
|
/** Instantiate a new signature from the given encoded string.
|
||||||
* Instantiate a new signature from the given encoded string.
|
*
|
||||||
*
|
* @param value
|
||||||
* @param value The input data.
|
* The input data.
|
||||||
* @return The new signature.
|
* @return
|
||||||
*/
|
* The new signature.
|
||||||
|
*/
|
||||||
def fromEncoded(value: Encoded): Signature =
|
def fromEncoded(value: Encoded): Signature =
|
||||||
value.decode()
|
value.decode()
|
||||||
|
|
||||||
given CanEqual[Signature, Signature] = CanEqual.derived
|
given CanEqual[Signature, Signature] = CanEqual.derived
|
||||||
|
|
||||||
extension (sig: Signature)
|
extension (sig: Signature)
|
||||||
/**
|
/** @return
|
||||||
* @return The underlying byte array.
|
* The underlying byte array.
|
||||||
*/
|
*/
|
||||||
def unwrap(): Array[Byte] = sig
|
def unwrap(): Array[Byte] = sig
|
||||||
|
|
||||||
/**
|
/** @return
|
||||||
* @return This signature, encoded using base64.
|
* This signature, encoded using base64.
|
||||||
*/
|
*/
|
||||||
def toBase64(): B64 = Base64Encoder.encode(sig)
|
def toBase64(): B64 = Base64Encoder.encode(sig)
|
||||||
|
|
||||||
/**
|
/** @return
|
||||||
* @return This signature, encoded using base64-url.
|
* This signature, encoded using base64-url.
|
||||||
*/
|
*/
|
||||||
def toBase64Url(): B64Url = Base64Encoder.encodeUrl(sig)
|
def toBase64Url(): B64Url = Base64Encoder.encodeUrl(sig)
|
||||||
|
|
||||||
/**
|
/** @return
|
||||||
* @return This signature, encoded using hex.
|
* This signature, encoded using hex.
|
||||||
*/
|
*/
|
||||||
def toHex(): Hex = HexEncoder.encode(sig)
|
def toHex(): Hex = HexEncoder.encode(sig)
|
||||||
|
|
||||||
end Signature
|
end Signature
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,50 @@
|
||||||
package gs.crypto.v0
|
package gs.crypto.v0
|
||||||
|
|
||||||
/**
|
/** Used to communicate the calculated validity of some [[Signature]].
|
||||||
* Used to communicate the calculated validity of some [[Signature]].
|
|
||||||
*
|
*
|
||||||
* @param name The enumeration name.
|
* @param name
|
||||||
|
* The enumeration name.
|
||||||
*/
|
*/
|
||||||
sealed abstract class SignatureValidity(val name: String):
|
sealed abstract class SignatureValidity(val name: String):
|
||||||
/** @inheritDocs */
|
|
||||||
override def equals(obj: Any): Boolean =
|
/** @inheritDocs
|
||||||
|
*/
|
||||||
|
override def equals(obj: Any): Boolean =
|
||||||
obj match
|
obj match
|
||||||
case other: SignatureValidity => name == other.name
|
case other: SignatureValidity => name == other.name
|
||||||
case _ => false
|
case _ => false
|
||||||
|
|
||||||
/** @inheritDocs */
|
/** @inheritDocs
|
||||||
|
*/
|
||||||
override def hashCode(): Int = name.hashCode()
|
override def hashCode(): Int = name.hashCode()
|
||||||
|
|
||||||
/** @inheritDocs */
|
/** @inheritDocs
|
||||||
|
*/
|
||||||
override def toString(): String = name
|
override def toString(): String = name
|
||||||
|
|
||||||
object SignatureValidity:
|
object SignatureValidity:
|
||||||
|
|
||||||
/**
|
/** Map a Boolean value to validity.
|
||||||
* Map a Boolean value to validity.
|
*
|
||||||
*
|
* - True: Valid
|
||||||
* - True: Valid
|
* - False: Invalid
|
||||||
* - False: Invalid
|
*
|
||||||
*
|
* @param isValid
|
||||||
* @param isValid Whether the signature is valid or not.
|
* Whether the signature is valid or not.
|
||||||
* @return The [[SignatureValidity]] selected for the given validity.
|
* @return
|
||||||
*/
|
* The [[SignatureValidity]] selected for the given validity.
|
||||||
|
*/
|
||||||
def apply(isValid: Boolean): SignatureValidity =
|
def apply(isValid: Boolean): SignatureValidity =
|
||||||
if isValid then Valid else Invalid
|
if isValid then Valid else Invalid
|
||||||
|
|
||||||
given CanEqual[SignatureValidity, SignatureValidity] = CanEqual.derived
|
given CanEqual[SignatureValidity, SignatureValidity] = CanEqual.derived
|
||||||
|
|
||||||
/**
|
/** The [[Signature]] is valid.
|
||||||
* The [[Signature]] is valid.
|
*/
|
||||||
*/
|
|
||||||
case object Valid extends SignatureValidity("valid")
|
case object Valid extends SignatureValidity("valid")
|
||||||
|
|
||||||
/**
|
/** The [[Signature]] is invalid.
|
||||||
* The [[Signature]] is invalid.
|
*/
|
||||||
*/
|
|
||||||
case object Invalid extends SignatureValidity("invalid")
|
case object Invalid extends SignatureValidity("invalid")
|
||||||
|
|
||||||
end SignatureValidity
|
end SignatureValidity
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package gs.crypto.v0
|
package gs.crypto.v0
|
||||||
|
|
||||||
/**
|
/** Used to verify cryptographic signatures.
|
||||||
* Used to verify cryptographic signatures.
|
|
||||||
*/
|
*/
|
||||||
trait SignatureVerifier[F[_]]:
|
trait SignatureVerifier[F[_]]:
|
||||||
def verify(signature: Signature): F[SignatureValidity]
|
def verify(signature: Signature): F[SignatureValidity]
|
||||||
|
|
|
||||||
|
|
@ -3,23 +3,28 @@ package gs.crypto.v0
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
/**
|
/** Used to calculate cryptographic signatures.
|
||||||
* Used to calculate cryptographic signatures.
|
|
||||||
*/
|
*/
|
||||||
trait Signer[F[_]]:
|
trait Signer[F[_]]:
|
||||||
/**
|
/** Calculate a signature for the given data.
|
||||||
* Calculate a signature for the given data.
|
*
|
||||||
*
|
* @param data
|
||||||
* @param data The input data.
|
* The input data.
|
||||||
* @return The calculated signature.
|
* @return
|
||||||
*/
|
* The calculated signature.
|
||||||
|
*/
|
||||||
def sign(data: Array[Byte]): F[Signature]
|
def sign(data: Array[Byte]): F[Signature]
|
||||||
|
|
||||||
/**
|
/** Calculate a signature for the given data.
|
||||||
* Calculate a signature for the given data.
|
*
|
||||||
*
|
* @param data
|
||||||
* @param data The input data.
|
* The input data.
|
||||||
* @param charset The character set of the input data.
|
* @param charset
|
||||||
* @return The calculated signature.
|
* The character set of the input data.
|
||||||
*/
|
* @return
|
||||||
def sign(data: String, charset: Charset = StandardCharsets.UTF_8): F[Signature]
|
* The calculated signature.
|
||||||
|
*/
|
||||||
|
def sign(
|
||||||
|
data: String,
|
||||||
|
charset: Charset = StandardCharsets.UTF_8
|
||||||
|
): F[Signature]
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,18 @@ package gs.crypto.v0
|
||||||
|
|
||||||
import cats.Applicative
|
import cats.Applicative
|
||||||
|
|
||||||
/**
|
/** Implementation of [[KeyLoader]] that loads keys directly from input strings.
|
||||||
* Implementation of [[KeyLoader]] that loads keys directly from input strings.
|
|
||||||
*
|
*
|
||||||
* @param config The key loader configuration.
|
* @param config
|
||||||
|
* The key loader configuration.
|
||||||
*/
|
*/
|
||||||
class StringKeyLoader[F[_]: Applicative](
|
class StringKeyLoader[F[_]: Applicative](
|
||||||
val config: BaseKeyLoader.Config
|
val config: BaseKeyLoader.Config
|
||||||
) extends BaseKeyLoader[F]:
|
) extends BaseKeyLoader[F]:
|
||||||
|
|
||||||
/** @inheritDocs */
|
/** @inheritDocs
|
||||||
|
*/
|
||||||
override def loadKey(
|
override def loadKey(
|
||||||
location: String
|
location: String
|
||||||
): F[Either[KeyLoadError, Array[Byte]]] =
|
): F[Either[KeyLoadError, Array[Byte]]] =
|
||||||
Applicative[F].pure(prepareKey(location))
|
Applicative[F].pure(prepareKey(location))
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,27 @@
|
||||||
package gs.crypto.v0.eddsa
|
package gs.crypto.v0.eddsa
|
||||||
|
|
||||||
import cats.effect.Sync
|
import cats.effect.Sync
|
||||||
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters
|
|
||||||
import gs.crypto.v0.Signature
|
import gs.crypto.v0.Signature
|
||||||
import gs.crypto.v0.Signer
|
import gs.crypto.v0.Signer
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets
|
||||||
|
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters
|
||||||
|
|
||||||
/**
|
/** Implementation of [[Signer]] that uses the Ed25519 system to calculate
|
||||||
* Implementation of [[Signer]] that uses the Ed25519 system to calculate
|
|
||||||
* signatures.
|
* signatures.
|
||||||
*
|
*
|
||||||
* See: [[Ed25519Verifier]]
|
* See: [[Ed25519Verifier]]
|
||||||
*
|
*
|
||||||
* @param privateKey The private key.
|
* @param privateKey
|
||||||
|
* The private key.
|
||||||
*/
|
*/
|
||||||
final class Ed25519Signer[F[_]: Sync](
|
final class Ed25519Signer[F[_]: Sync](
|
||||||
privateKey: Array[Byte]
|
privateKey: Array[Byte]
|
||||||
) extends Signer[F]:
|
) extends Signer[F]:
|
||||||
private lazy val params = new Ed25519PrivateKeyParameters(privateKey)
|
private lazy val params = new Ed25519PrivateKeyParameters(privateKey)
|
||||||
|
|
||||||
/** @inheritDocs */
|
/** @inheritDocs
|
||||||
|
*/
|
||||||
override def sign(data: Array[Byte]): F[Signature] =
|
override def sign(data: Array[Byte]): F[Signature] =
|
||||||
Sync[F].delay {
|
Sync[F].delay {
|
||||||
val s = new org.bouncycastle.crypto.signers.Ed25519Signer()
|
val s = new org.bouncycastle.crypto.signers.Ed25519Signer()
|
||||||
|
|
@ -29,9 +30,10 @@ final class Ed25519Signer[F[_]: Sync](
|
||||||
Signature(s.generateSignature())
|
Signature(s.generateSignature())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritDocs */
|
/** @inheritDocs
|
||||||
|
*/
|
||||||
override def sign(
|
override def sign(
|
||||||
data: String,
|
data: String,
|
||||||
charset: Charset = StandardCharsets.UTF_8
|
charset: Charset = StandardCharsets.UTF_8
|
||||||
): F[Signature] =
|
): F[Signature] =
|
||||||
sign(data.getBytes(charset))
|
sign(data.getBytes(charset))
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,27 @@
|
||||||
package gs.crypto.v0.eddsa
|
package gs.crypto.v0.eddsa
|
||||||
|
|
||||||
import cats.effect.Sync
|
import cats.effect.Sync
|
||||||
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters
|
|
||||||
import gs.crypto.v0.Signature
|
import gs.crypto.v0.Signature
|
||||||
import gs.crypto.v0.SignatureVerifier
|
|
||||||
import gs.crypto.v0.SignatureValidity
|
import gs.crypto.v0.SignatureValidity
|
||||||
|
import gs.crypto.v0.SignatureVerifier
|
||||||
|
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters
|
||||||
|
|
||||||
/**
|
/** Implementation of [[SignatureVerifier]] that uses the Ed25519 system to
|
||||||
* Implementation of [[SignatureVerifier]] that uses the Ed25519 system to
|
|
||||||
* verify signatures.
|
* verify signatures.
|
||||||
*
|
*
|
||||||
* See: [[Ed25519Signer]]
|
* See: [[Ed25519Signer]]
|
||||||
*
|
*
|
||||||
* @param publicKey The public key.
|
* @param publicKey
|
||||||
|
* The public key.
|
||||||
*/
|
*/
|
||||||
final class Ed25519Verifier[F[_]: Sync](
|
final class Ed25519Verifier[F[_]: Sync](
|
||||||
publicKey: Array[Byte]
|
publicKey: Array[Byte]
|
||||||
) extends SignatureVerifier[F]:
|
) extends SignatureVerifier[F]:
|
||||||
private lazy val params = new Ed25519PublicKeyParameters(publicKey)
|
private lazy val params = new Ed25519PublicKeyParameters(publicKey)
|
||||||
|
|
||||||
/** @inheritDocs */
|
/** @inheritDocs
|
||||||
override def verify(signature: Signature): F[SignatureValidity] =
|
*/
|
||||||
|
override def verify(signature: Signature): F[SignatureValidity] =
|
||||||
Sync[F].delay {
|
Sync[F].delay {
|
||||||
val s = new org.bouncycastle.crypto.signers.Ed25519Signer()
|
val s = new org.bouncycastle.crypto.signers.Ed25519Signer()
|
||||||
val _ = s.init(false, params)
|
val _ = s.init(false, params)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue