Guest User

main.swift

a guest
Dec 9th, 2022
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 9.62 KB | Cybersecurity | 0 0
  1. import Foundation
  2. import Command
  3. import Crypto
  4.  
  5. struct Signature: Codable {
  6.     let signature: Data
  7. }
  8.  
  9. struct KeyPair: Codable {
  10.     let priv: Data
  11.     let pub: Data
  12.     init() {
  13.         var initial_priv: [UInt8] = []
  14.         var initial_pub: [UInt8] = []
  15.         for _ in 0...65 {
  16.             var subkey: [UInt8] = []
  17.             for _ in 0...63 {
  18.                 subkey.append(UInt8.random(in:0...255))
  19.             }
  20.  
  21.             initial_priv.append(contentsOf: subkey)
  22.  
  23.             var hash = Data(bytes: subkey)
  24.             for _ in 1...255 {
  25.                 hash = try! SHA512.hash(hash)
  26.             }
  27.             initial_pub.append(contentsOf: hash)
  28.         }
  29.         priv = Data(bytes: initial_priv)
  30.         pub = Data(bytes: initial_pub)
  31.     }
  32. }
  33.  
  34. struct BChain {
  35.     public static func generateKeyPair() -> KeyPair {
  36.         return KeyPair()
  37.     }
  38.  
  39.     public static func sign(_ hash: Data, withKeyPair keypair: KeyPair) -> Data {
  40.         var signature: [UInt8] = []
  41.         var distance = 255*64
  42.         for i in 0...65 {
  43.             let byte: UInt8
  44.             switch i {
  45.                 case 64:
  46.                     byte = numericCast(distance/256)
  47.                 case 65:
  48.                     byte = numericCast(distance-distance/256*256)
  49.                 default:
  50.                     byte = hash[i]
  51.             }
  52.             let subkey = keypair.priv[(i*64)...(i*64+63)]
  53.             var subsig = subkey
  54.             for _ in 0..<byte {
  55.                 subsig = try! SHA512.hash(subsig)
  56.                 if i < 64 {
  57.                     distance -= 1
  58.                 }
  59.             }
  60.             signature.append(contentsOf: subsig)
  61.         }
  62.         return Data(bytes: signature)
  63.     }
  64.  
  65.     public static func verify(_ sig: Signature, hash: Data, key keypair: KeyPair) -> Bool {
  66.         var value: [UInt8] = []
  67.         var distance: Int = 0
  68.         for i in 0...65 {
  69.             let subsig = sig.signature[(i*64)...(i*64+63)]
  70.             let target = keypair.pub[(i*64)...(i*64+63)]
  71.             var currentSig: Data = subsig
  72.             for j in 0...255 {
  73.                 if currentSig == target {
  74.                     value.append(numericCast(255 - j))
  75.                     if (i < 64) {
  76.                         distance += j
  77.                     }
  78.                     break;
  79.                 }
  80.                 do {
  81.                     currentSig = try SHA512.hash(currentSig)
  82.                 } catch {
  83.                     return false
  84.                 }
  85.             }
  86.             if i != value.count-1 {
  87.                 return false
  88.             }
  89.         }
  90.         if distance != Int(value[64])*256+Int(value[65]) {
  91.             return false
  92.         }
  93.         for i in 0...63 {
  94.             if value[i] != hash[i] {
  95.                 return false
  96.             }
  97.         }
  98.         return true
  99.     }
  100. }
  101.  
  102. struct BChainCommand: Command {
  103.     var arguments: [CommandArgument] {
  104.         return [
  105.                 .argument(name: "command", help: [
  106.                                                     "keypair: generates a public and private keypair",
  107.                                                     "sign: sign a file",
  108.                                                     "verify: verify a file against a signature",
  109.                                                  ]),
  110.                ]
  111.     }
  112.  
  113.     var options: [CommandOption] {
  114.         return [
  115.                 .value(name: "output", short: "o", help: ["output file"]),
  116.                 .value(name: "key", short: "k", help: ["key file"]),
  117.                 .value(name: "input", short: "i", help: ["input file"]),
  118.                 .value(name: "signature", short: "s", help: ["signature file"]),
  119.                ]
  120.     }
  121.  
  122.     var help: [String] {
  123.         return ["Does stuff.",
  124.                 "And more stuff?"
  125.                ]
  126.     }
  127.  
  128.     func run(using ctx: CommandContext) throws -> Future<Void> {
  129.         let console = ctx.console
  130.         switch ctx.arguments["command"] {
  131.  
  132.             case "keypair":
  133.                 guard let output = ctx.options["output"] else {
  134.                     console.print("need an output file")
  135.                     exit(-1)
  136.                 }
  137.                 let keypair = BChain.generateKeyPair()
  138.                 let encoder = JSONEncoder()
  139.                 encoder.outputFormatting = [JSONEncoder.OutputFormatting.prettyPrinted, .sortedKeys]
  140.                 let data = try! encoder.encode(keypair)
  141.                 let hash = try! SHA512.hash(keypair.pub)
  142.                 console.print("outputting keypair: \(hash.hexEncodedString())")
  143.                 let outputFilePath = URL(fileURLWithPath: output)
  144.                 do {
  145.                     try data.write(to:outputFilePath)
  146.                 } catch {
  147.                     console.print("Error writing key: \(error)")
  148.                     exit(-1)
  149.                 }
  150.  
  151.             case "sign":
  152.                 //import key
  153.                 guard let key = ctx.options["key"] else {
  154.                     console.print("need a key file")
  155.                     exit(-1)
  156.                 }
  157.                 let decoder = JSONDecoder()
  158.                 let keypair: KeyPair
  159.                 do {
  160.                     keypair = try decoder.decode(KeyPair.self, from: try Data(contentsOf: URL(fileURLWithPath: key)))
  161.                 } catch {
  162.                     console.print("Error importing key: \(error)")
  163.                     exit(-1)
  164.                 }
  165.  
  166.                 //read input
  167.                 guard let input = ctx.options["input"] else {
  168.                     console.print("need an input file")
  169.                     exit(-1)
  170.                 }
  171.                 let data: Data
  172.                 do {
  173.                     data = try Data(contentsOf: URL(fileURLWithPath: input))
  174.                 } catch {
  175.                     console.print("Error loading input file: \(error)")
  176.                     exit(-1)
  177.                 }
  178.  
  179.                 //hash input
  180.                 let hash: Data
  181.                 do {
  182.                     hash = try SHA512.hash(data)
  183.                 } catch {
  184.                     console.print("Error hashing input: \(error)")
  185.                     exit(-1)
  186.                 }
  187.  
  188.                 //calculate signature
  189.                 let sig = Signature(signature: BChain.sign(hash, withKeyPair: keypair))
  190.  
  191.                 //output signature
  192.                 guard let output = ctx.options["output"] else {
  193.                     console.print("need an output file")
  194.                     exit(-1)
  195.                 }
  196.                 let encoder = JSONEncoder()
  197.                 encoder.outputFormatting = [JSONEncoder.OutputFormatting.prettyPrinted, .sortedKeys]
  198.                 let json = try! encoder.encode(sig)
  199.                 let outputFilePath = URL(fileURLWithPath: output)
  200.                 do {
  201.                     try json.write(to:outputFilePath)
  202.                 } catch {
  203.                     console.print("Error writing key: \(error)")
  204.                     exit(-1)
  205.                 }
  206.  
  207.             case "verify":
  208.                 //import key
  209.                 guard let key = ctx.options["key"] else {
  210.                     console.print("need a key file")
  211.                     exit(-1)
  212.                 }
  213.                 let decoder = JSONDecoder()
  214.                 let keypair: KeyPair
  215.                 do {
  216.                     keypair = try decoder.decode(KeyPair.self, from: try Data(contentsOf: URL(fileURLWithPath: key)))
  217.                 } catch {
  218.                     console.print("Error importing key: \(error)")
  219.                     exit(-1)
  220.                 }
  221.  
  222.                 //read input
  223.                 guard let input = ctx.options["input"] else {
  224.                     console.print("need an input file")
  225.                     exit(-1)
  226.                 }
  227.                 let data: Data
  228.                 do {
  229.                     data = try Data(contentsOf: URL(fileURLWithPath: input))
  230.                 } catch {
  231.                     console.print("Error loading input file: \(error)")
  232.                     exit(-1)
  233.                 }
  234.  
  235.                 //hash input
  236.                 let hash: Data
  237.                 do {
  238.                     hash = try SHA512.hash(data)
  239.                 } catch {
  240.                     console.print("Error hashing input: \(error)")
  241.                     exit(-1)
  242.                 }
  243.  
  244.                 //import signature
  245.                 guard let signature = ctx.options["signature"] else {
  246.                     console.print("need a signature file")
  247.                     exit(-1)
  248.                 }
  249.                 let sig: Signature
  250.                 do {
  251.                     sig = try decoder.decode(Signature.self, from: try Data(contentsOf: URL(fileURLWithPath: signature)))
  252.                 } catch {
  253.                     console.print("Error importing signature: \(error)")
  254.                     exit(-1)
  255.                 }
  256.  
  257.                 if BChain.verify(sig, hash: hash, key: keypair) {
  258.                     console.print("verified")
  259.                 } else {
  260.                     console.print("verification failed")
  261.                     exit(-1)
  262.                 }
  263.  
  264.  
  265.             default:
  266.                 console.print("Command is unrecognized.")
  267.                 exit(-1)
  268.         }
  269.         return .done(on: ctx.container)
  270.     }
  271. }
  272.  
  273. let console = Terminal()
  274. let thread = MultiThreadedEventLoopGroup(numberOfThreads: 1)
  275. var env = Environment(name: "Test", isRelease: false, arguments: CommandLine.arguments)
  276. var container = BasicContainer(config: Config(), environment: env, services: Services(), on: thread)
  277. do {
  278.     try console.run(BChainCommand(), input: &env.commandInput, on: container).wait()
  279. } catch {
  280.     exit(-1)
  281. }
  282. exit(0)
Advertisement
Add Comment
Please, Sign In to add comment