【问题标题】:Given final block not properly padded, encryption issue鉴于最终块未正确填充,加密问题
【发布时间】:2017-06-04 05:21:17
【问题描述】:

我是密码新手,我总是犯这个错误

有一个服务:http://aesencryption.net/ 所以我加密文本以便将服务结果放入我的测试用例中

key: passwd
original: mysecret
bytes: 128 (*don't know what it means but anyway..)
encrypted: EaDf/5rVXY3qMeQx1JmPCw==

我有这个 scala 代码

import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec

import com.github.kondaurovdev.snippets.helper.{CryptoHelper, TryHelper}
import org.apache.commons.codec.binary.Base64

object Crypter {

  def apply(secret: String): Either[String, Crypter] = {
    for (
      s <- CryptoHelper.getSecretKey(secret).left.map(err => s"Can't get secretKeySpec: $err").right
    ) yield new Crypter(s)
  }

}

class Crypter(secretKey: SecretKeySpec) {

  def encrypt(input: String): Either[String, String] = {

    TryHelper.tryBlock({
      val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
      cipher.init(Cipher.ENCRYPT_MODE, secretKey)
      val encrypted = cipher.doFinal(input.getBytes("UTF-8"))
      Base64.encodeBase64String(encrypted)
    }, "Can't encrypt text")

  }

  //input = base64 encoded string
  def decrypt(input: String): Either[String, String] = {

    for (
      res <- {
        TryHelper.tryBlock({
          val cipher = Cipher.getInstance("AES/ECB/PKCS5Padding")
          cipher.init(Cipher.DECRYPT_MODE, secretKey)
          val decrypted = cipher.doFinal(Base64.decodeBase64(input))
          new String(decrypted)
        }, "Error while decrypting")
      }.right
    ) yield res

  }


}

object CryptoHelper {

  def getSecretKey(myKey: String): Either[String, SecretKeySpec] = {
    TryHelper.tryBlock({
      var key = myKey.getBytes("UTF-8")
      val sha = MessageDigest.getInstance("SHA-1")
      key = sha.digest(key)
      key = util.Arrays.copyOf(key, 16) // use only first 128 bit
      new SecretKeySpec(key, "AES")
    }, "Can't build secretKey")
  }

}

object TryHelper {

  def tryBlock[R, E <: Throwable](block: => R, errPrefix: String = "", handle: errorPF = handlePF): Either[String, R] = {
    tryToEither(block).left.map(err => {
      var msg = err.getMessage
      if (errPrefix.nonEmpty) msg = s"$errPrefix: $msg"
      msg
    })
  }

}

我有这个测试用例:

import com.github.kondaurovdev.snippets.Crypter
import org.specs2.mutable.Specification

class CrypterSpec extends Specification {

  "Crypter" should {

    val crypter = Crypter("passwd")

    "decrypt" in {

      "case 1" in {
        crypter.right.flatMap(_.decrypt("eRKUj0EIXgyqzNFwHWYSLw==")) must beRight("asd")
      }

    }

    "encrypt" in {

      "case 1" in {
        crypter.right.flatMap(_.encrypt("asd")) must beRight("eRKUj0EIXgyqzNFwHWYSLw==")
      }

    }

  }

}

但是这些测试没有通过..

> snippets/testOnly snippets.CrypterSpec
[info] CrypterSpec
[info] 
[info] Crypter should
[info]   decrypt
[error]     x case 1
[error]      'Left(Error while decrypting: Given final block not properly padded)' is not Right (CrypterSpec.scala:15)
[info] 
[info]   encrypt
[error]     x case 1
[error]      'Right(bVkPlx7E0OjhCWFyIHzM5Q==)' is Right but 'bVkPlx7E0OjhCWFyIHzM5Q==' is not equal to 'eRKUj0EIXgyqzNFwHWYSLw==' (CrypterSpec.scala:23)
[error] Actual:   bVkPlx7E0OjhCWFyIHzM5Q==
[error] Expected: eRKUj0EIXgyqzNFwHWYSLw==
[info] 
[info] 
[info] 
[info] Total for specification CrypterSpec
[info] Finished in 6 minutes 3 seconds, 588 ms
[info] 2 examples, 2 failures, 0 error
[info] 
[error] Failed: Total 2, Failed 2, Errors 0, Passed 0
[error] Failed tests:
[error]         snippets.CrypterSpec
[error] (snippets/test:testOnly) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 366 s, completed Jun 3, 2017 11:24:16 PM

【问题讨论】:

  • 我不知道 scala,但如果这是 java,那么返回 new String(decrypted) 将是一个错误。您在加密时所做的一切都必须在解密时un完成,因此您应该返回new String(decrypted,"UTF-8")。但是,这不会导致 BadPaddingException,所以我还没有看到那是什么。我可能会尝试重新创建您的代码的 Java 版本,看看会发生什么。

标签: java encryption aes


【解决方案1】:

由于我不是 scala 程序员,我将您的代码转换为我认为等效的 Java 代码。我加密“asd”的结果与你的匹配——输出为bVkPlx7E0OjhCWFyIHzM5Q==。因此,我得出的结论是,您对输出应为 eRKUj0EIXgyqzNFwHWYSLw== 的期望是不正确的。

如果您使用的是您引用的测试结果网站,请注意,他们可能没有使用与您相同的函数将字符串映射到 AES 密钥。将低熵字符串转换为对称密钥的推荐算法包括 pbkdf2、bcrypt、scrypt 等。这些是专门为这种情况设计的。

【讨论】:

  • 当我在 bVkPlx7E0OjhCWFyIHzM5Q 上更改 eRKUj0EIXgyqzNFwHWYSLw 时,此错误消失,测试成功。你说得对,都是因为我的错误预期。我刚刚将代码(来自网站,查看网站底部)转换为等效的 scala,并认为它应该可以工作。谢谢你的帮助。我想使用加密来加密配置文件中的密码并在应用程序需要时解密它们
猜你喜欢
  • 2013-12-02
  • 2015-05-22
  • 1970-01-01
  • 2014-01-22
  • 1970-01-01
  • 2015-03-28
  • 1970-01-01
  • 2011-12-24
  • 2015-06-18
相关资源
最近更新 更多