代码之家  ›  专栏  ›  技术社区  ›  Alain Stulz

Epub字体损坏无法工作

  •  0
  • Alain Stulz  · 技术社区  · 9 年前

    我正在使用Swift 2为iOS创建一个EPUB 3阅读器。

    我目前面临的问题是字体混淆/字体损坏。我已经阅读了一篇教程,介绍了如何在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)
                    }
                }
            }
        }
    }
    

    如果你知道错误可能在哪里,请告诉我。

    1 回复  |  直到 9 年前
        1
  •  0
  •   Alain Stulz    9 年前

    我想通了,这是工作代码:

    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
      }
    }