2015-09-23 5 views
0

Я создаю читатель EPUB 3 для прошивкой с помощью Swift 2.Epub шрифт коверкая не работает

Проблемы В настоящее время я облицовка с коверкая запутывание шрифта/шрифт. Я прочитал учебник, в котором рассказывается, как это сделать в Swift, и интегрировал его в свой проект с некоторыми изменениями.

Когда я загружаю запутанный epub в свое приложение, шрифты загружаются неправильно и возвращаются к другим системным шрифтам. Когда я загружаю epub с теми же шрифтами, но не запутывается, все выглядит отлично. Очевидно, это означает, что с моим кодом обфускации что-то не так, но я не могу, чтобы жизнь меня обнаружила ошибку.

Вот мой код:

public struct Crypto { 

    public func obfuscateFontIDPF(data:NSData, key:String) -> NSData { 
    let source = data 
    var destination = [UInt8]() 
    let shaKey = key.sha1() 
    let keyData = shaKey.utf8Array 

    var arr = [UInt8](count: source.length, repeatedValue: 0) 
    source.getBytes(&arr, length:source.length) 

    var outer = 0 
    while outer < 52 && arr.isEmpty == false { 
     var inner = 0 
     while inner < 20 && arr.isEmpty == false { 
      let byte = arr.removeAtIndex(0)  //Assumes read advances file position 
      let sourceByte = byte 
      let keyByte = keyData[inner] 
      let obfuscatedByte = sourceByte^keyByte 
      destination.append(obfuscatedByte) 
      inner++ 
     } 
     outer++ 
    } 
    if arr.isEmpty == false { 
     while arr.isEmpty == false { 
      let byte = arr.removeAtIndex(0) 
      destination.append(byte) 
     } 
    } 

    let newData = NSData(bytes: &destination, length:  destination.count*sizeof(UInt8)) 
    return newData 
    } 
} 

extension String { 
    func sha1() -> String { 
    var selfAsSha1 = "" 

    if let data = self.dataUsingEncoding(NSUTF8StringEncoding) 
    { 
     var digest = [UInt8](count: Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0) 
     CC_SHA1(data.bytes, CC_LONG(data.length), &digest) 

     for index in 0..<CC_SHA1_DIGEST_LENGTH 
     { 
      selfAsSha1 += String(format: "%02x", digest[Int(index)]) 
     } 
    } 

    return selfAsSha1 
    } 

    var utf8Array: [UInt8] { 
    return Array(utf8) 
    } 
} 

И здесь я вызываю метод запутывания:

func parserDidEndDocument(parser: NSXMLParser) { 
     if encryptedFilePaths!.count != 0 { 
     for file in encryptedFilePaths! { 
      let epubMainDirectoryPath = NSString(string: epubBook!.epubMainFolderPath!).stringByDeletingLastPathComponent 
      let fullFilePath = epubMainDirectoryPath.stringByAppendingString("/" + file) 
      let url = NSURL(fileURLWithPath: fullFilePath) 
      if let source = NSData(contentsOfURL: url) { 
       let decryptedFont = Crypto().obfuscateFontIDPF(source, key: self.epubBook!.encryptionKey!) 
       do { 
        try decryptedFont.writeToFile(fullFilePath, options: .DataWritingAtomic) 
       } catch { 
        print(error) 
       } 
      } 
     } 
    } 
} 

Если вы видите, где ошибка может быть, пожалуйста, дайте мне знать.

+0

Интересно, что с помощью реального шифрования (AES) и Common Crypto, вероятно, будет несколько порядков быстрее. – zaph

+0

@zaph Да, это не я, кто сделал стандарт Epub, к сожалению. Кроме того, это только защита от де-юре, очень просто распаковать epub и извлечь шрифт. Это сделано только для защиты издателя на законных основаниях. –

ответ

0

Я понял это, вот рабочий код:

private func obfuscateData(data: NSData, key: String) -> NSData { 
    var destinationBytes = [UInt8]() 

    // Key needs to be SHA1 hash with length of exactly 20 chars 
    let hashedKeyBytes = generateHashedBytesFromString(key) 

    var sourceBytes = [UInt8](count: data.length, repeatedValue: 0) 
    data.getBytes(&sourceBytes, length: data.length) 

    var outerCount = 0 
    while outerCount < 52 && sourceBytes.isEmpty == false { 
     var innerCount = 0 
     while innerCount < 20 && sourceBytes.isEmpty == false { 
      let sourceByte = sourceBytes.removeAtIndex(0) 
      let keyByte = hashedKeyBytes[innerCount] 
      let obfuscatedByte = (sourceByte^keyByte) 
      destinationBytes.append(obfuscatedByte) 
      innerCount += 1 
     } 
     outerCount += 1 
    } 

    destinationBytes.appendContentsOf(sourceBytes) 
    let destinationData = NSData(bytes: &destinationBytes, length: destinationBytes.count*sizeof(UInt8)) 
    sourceBytes.removeAll(keepCapacity: false) 
    destinationBytes.removeAll(keepCapacity: false) 
    return destinationData 
} 

/// Convert the key string to a SHA1 hashed Byte Array 
private func generateHashedBytesFromString(string: String) -> [UInt8] { 
    var resultBytes = [UInt8]() 
    var hashedString = string.sha1() 

    for _ in 0.stride(to: hashedString.characters.count, by: 2) { 
     let character = "0x\(hashedString.returnTwoCharacters())" 
     resultBytes.append(UInt8(strtod(character, nil))) 
    } 
    return resultBytes 
} 


extension String { 
    func sha1() -> String { 
    var selfAsSha1 = "" 

    if let data = self.dataUsingEncoding(NSUTF8StringEncoding) { 
     var digest = [UInt8](count: Int(CC_SHA1_DIGEST_LENGTH), repeatedValue: 0) 
     CC_SHA1(data.bytes, CC_LONG(data.length), &digest) 

     for index in 0..<CC_SHA1_DIGEST_LENGTH { 
      selfAsSha1 += String(format: "%02x", digest[Int(index)]) 
     } 
    } 

    return selfAsSha1 
    } 

    mutating func returnTwoCharacters() -> String { 
     var characters: String = "" 
     characters.append(self.removeAtIndex(startIndex)) 
     characters.append(self.removeAtIndex(startIndex)) 
     return characters 
    } 
}