【问题标题】:Output block size with AES使用 AES 的输出块大小
【发布时间】:2013-06-02 01:06:03
【问题描述】:

我正在尝试使用带有 16 字节密钥的 16 字节的 Racket Crypto libraryencrypt 块。我期望有一个 16 字节的输出块,但我得到一个 32 字节的输出块。 一个 15 字节的输入块给出一个 16 位的输出。

#lang racket

(require (planet vyzo/crypto))

(bytes-length (encrypt cipher:aes-128-ecb
                       (string->bytes/latin-1 "0123456789ABCDEF") ; 16-byte key
                       (make-bytes 16) ; IV
                       (string->bytes/latin-1 "0123456789ABCDEF"))) ; 16-byte data
; -> 32

(bytes-length (encrypt cipher:aes-128-ecb
                       (string->bytes/latin-1 "0123456789ABCDEF") ; 16-byte key
                       (make-bytes 16)
                       (string->bytes/latin-1 "0123456789ABCDE"))) ; 15-byte data
; -> 16

我是不是哪里错了?这是因为填充吗?

注意:我知道 ECB 模式的问题,我的目标是实现 CBC 模式。

【问题讨论】:

    标签: encryption cryptography aes racket


    【解决方案1】:

    你是对的,这是因为填充。不幸的是,vyzo/crypto lib 的 API 不允许您轻松禁用填充(正确的是,请参阅下面的警告)。

    如何禁用填充

    但是,基于此Thread on the Racket users mailing list,您可以像这样禁用填充:

    #lang racket
    
    (require (planet vyzo/crypto) (planet vyzo/crypto/util))
    
    (define (cipher-encrypt-unpadded type key iv)
      (lambda (ptext)
        (let ((octx (cipher-encrypt type key iv #:padding #f)))
          (bytes-append (cipher-update! octx ptext)
                        (cipher-final! octx)))))
    
    (define (cipher-decrypt-unpadded type key iv)
      (lambda (ctext)
        (let ((ictx (cipher-decrypt type key iv #:padding #f)))
          (bytes-append (cipher-update! ictx ctext)
                        (cipher-final! ictx)))))
    
    ; bytes-> bytes
    ; convenience function for encryption
    (define enc-aes-128-ecb-unpadded 
       (cipher-encrypt-unpadded cipher:aes-128-ecb 
                                (string->bytes/latin-1 "0123456789ABCDEF"); 16-byte key
                                (make-bytes 16)))
    
    ; bytes -> bytes
    ; convenience function for decryption       
    (define dec-aes-128-ecb-unpadded 
       (cipher-decrypt-unpadded cipher:aes-128-ecb 
                                (string->bytes/latin-1 "0123456789ABCDEF"); 16-byte key
                                (make-bytes 16)))
    
    (define message (string->bytes/latin-1 "0123456789ABCDEF")) ; 16-byte data
    
    (bytes-length (enc-aes-128-ecb-unpadded message))
    ; -> 16
    
    
    (dec-aes-128-ecb-unpadded (enc-aes-128-ecb-unpadded message))
    ; -> #"0123456789ABCDEF"
    

    这在我的机器上运行良好。此外,切换到 CBC 模式也很简单。

    警告

    当您禁用填充时,您的消息长度必须是块大小的倍数。对于 AES128,它是 16 字节的精确倍数。否则这个函数会在你的脸上爆炸:

    (enc-aes-128-ecb-unpadded (string->bytes/latin-1 "too short!"))
    EVP_CipherFinal_ex: libcrypto error: data not multiple of block length [digital envelope routines:EVP_EncryptFinal_ex:101183626] 
    

    【讨论】:

    • 非常感谢。正是我需要的。
    【解决方案2】:

    看起来所有输入都被填充到 next 块边界。这意味着 16 字节的输入将被填充到 32 字节的下一个边界。如果您的所有输入都是精确的块大小,那么您可以关闭填充。如果输入可以在块的中间结束,那么您将不得不打开填充。

    如果您要使用 CBC 模式,那么您可能还需要考虑身份验证。如果您确实需要它,那么 HMAC 可能是最容易上手的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-16
      • 2013-12-16
      • 1970-01-01
      • 2016-07-30
      相关资源
      最近更新 更多