Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env amm
- // This is free and unencumbered software released into the public domain.
- //
- // Anyone is free to copy, modify, publish, use, compile, sell, or
- // distribute this software, either in source code form or as a compiled
- // binary, for any purpose, commercial or non-commercial, and by any
- // means.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- // OTHER DEALINGS IN THE SOFTWARE.
- import $ivy.`dev.zio::zio:1.0.0-RC20`
- import zio._
- import $ivy.`org.bouncycastle:bcpg-jdk15on:1.65`
- import java.io._
- import java.security._
- import java.util.Date
- import org.bouncycastle.bcpg._
- import org.bouncycastle.jce.provider._
- import org.bouncycastle.openpgp._
- import org.bouncycastle.openpgp.operator._
- import org.bouncycastle.openpgp.operator.jcajce._
- object PGP {
- def bouncyCastleProvider: TaskLayer[Has[Provider]] =
- ZLayer.fromEffect(IO(new BouncyCastleProvider))
- def keyPairGenerator: RManaged[Has[Provider], KeyPairGenerator] = for {
- provider <- Managed.service[Provider]
- gen <- Managed.effect(KeyPairGenerator.getInstance("ed25519", provider))
- } yield gen
- def genKeyPair(kpg: KeyPairGenerator)(creationTime: Date): Task[PGPKeyPair] = for {
- rawkp <- IO(kpg.generateKeyPair())
- jcakp <- IO(new JcaPGPKeyPair(PublicKeyAlgorithmTags.EDDSA, rawkp, creationTime))
- } yield jcakp
- def makeRing(kp: PGPKeyPair, userId: String): RIO[Has[Provider], PGPKeyRing] = for {
- provider <- ZIO.service[Provider]
- certificationLevel = PGPSignature.POSITIVE_CERTIFICATION
- hashAlgorithmTag = HashAlgorithmTags.SHA256
- checksumCalculator <- IO(new JcaPGPDigestCalculatorProviderBuilder().setProvider(provider).build().get(hashAlgorithmTag))
- hashedPcks = null: PGPSignatureSubpacketVector
- unhashedPcks = null: PGPSignatureSubpacketVector
- keySignerBuilder = new JcaPGPContentSignerBuilder(kp.getPublicKey.getAlgorithm, hashAlgorithmTag).setProvider(provider)
- keyEncryptor = null: PBESecretKeyEncryptor
- ring <- IO(new PGPKeyRingGenerator(
- certificationLevel, kp, userId, checksumCalculator, hashedPcks, unhashedPcks, keySignerBuilder, keyEncryptor
- ).generateSecretKeyRing())
- } yield ring
- def loadRing(in: InputStream): Task[PGPKeyRing] =
- IO(new PGPPublicKeyRing(PGPUtil.getDecoderStream(in), new JcaKeyFingerprintCalculator))
- def saveRing(kr: PGPKeyRing, out: OutputStream): Task[Unit] =
- Managed.fromAutoCloseable(IO(new ArmoredOutputStream(out))).use { out =>
- IO(kr.encode(out))
- }
- }
- object Feederiken extends App {
- val ThreadCount = 8 // Adapt to your hardware
- // Beware: the computation times goes up with the exponential of the length
- val Prefix = Array[Byte](0xFE.toByte, 0xED.toByte)
- // Author name. Can be changed afterwards. Put an e-mail address in square brackets if desired.
- val UserId = "Anonymous"
- import PGP._
- def bruteForceKey(prefix: Array[Byte], creationTime: Date) =
- keyPairGenerator.use {
- genKeyPair(_)(creationTime).doUntil(_.getPublicKey.getFingerprint.startsWith(prefix))
- }
- def putBenchmark(n: Int, creationTime: Date) = {
- val program = keyPairGenerator.use { kpg =>
- def rec(n: Int): Task[Unit] =
- if (n <= 0) IO.unit
- else genKeyPair(kpg)(creationTime) *> rec(n - 1)
- rec(n)
- }
- for {
- (t, _) <- program.timed
- freq = 1e9 / t.toNanos * n
- _ <- console.putStrLn(s"Single-threaded hashrate: $freq Hz")
- } yield ()
- }
- def program = for {
- creationTime <- IO(new Date)
- // quick benchmark
- _ <- putBenchmark(10000, creationTime)
- // bruteforce in parallel
- tasks = List.fill(ThreadCount)(bruteForceKey(Prefix, creationTime))
- // append result to results.asc
- result <- tasks.head.raceAll(tasks.tail)
- resultRing <- makeRing(result, UserId)
- _ <- Managed.fromAutoCloseable(IO(new FileOutputStream("results.asc", true))).use(saveRing(resultRing, _))
- } yield ()
- def run(args: List[String]): zio.ZIO[zio.ZEnv, Nothing, zio.ExitCode] =
- program.provideCustomLayer(bouncyCastleProvider).exitCode
- }
- // Ammonite glue
- Feederiken.main(Array.empty)
Add Comment
Please, Sign In to add comment