在 ruby 中为文件生成 CRC16 校验和

Generating CRC16 checksums in ruby for files

首先,让我解释一下,我几乎不知道这意味着什么,所以如果我说了什么蠢话,请告诉我。

我正在开发一个系统,它将 xml 字符串和文件转换为 hexpair 字符串以嵌入智能卡并通过网络发送。这个位工作得很好。

然而,此过程的一部分还涉及为 string/file 生成校验和,为此我已经获得了一些示例 C# 代码(对于屏幕截图,抱歉,它取自 PDF 文件):

我的工作是将此代码转换为 Ruby,但我只取得了部分成功。

我得到了一些示例字符串和图像来测试它,所有这些都可以在本规范中找到

require 'spec_helper'
require 'checksum_calculator'

describe ChecksumCalculator do
  describe '.call' do
    subject { described_class.call(data) }

    context 'when passed xml' do
      let(:data) { '<Card><RegNo>00000003</><Title>Mr</><Initial>B</><Surname>Black</><PrintDate>01-Feb-2004</><ExpiryDate>Dec 2012</><Colour>Black</><Scheme>CSCS</><Type>Senior Manager</><IssuedBy>Construction Skills</><Foil>H+S Test</><Top>CONSTRUCTION SKILLS CERTIFICATION SCHEME</><Bottom>The registered holder of this card holds the~construction qualifications listed on the reverse</><Back><Line>NVQ Construction Site Management L5</></Back><LogoID>3</></Card>' }

      it 'returns "8B5A"' do
        expect(subject).to eq '8B5A'
      end
    end

    context 'when passed Lorem ipsum' do
      let(:data) { 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam ut consectetur justo, in semper enim. Curabitur placerat varius diam. Suspendisse dapibus dui sapien, ac mattis mi aliquam sit amet. Phasellus interdum magna et urna rutrum elementum. Fusce odio risus, laoreet vel velit sit amet, convallis egestas metus. Nunc tincidunt, ligula ut lobortis facilisis, nulla sem semper dui, eget consectetur ligula mi eu felis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Maecenas ipsum metus, feugiat eget pretium in, ultricies sit amet leo. Mauris sed facilisis turpis, quis porta sapien. In hac habitasse platea dictumst. Integer gravida, tortor nec pharetra ornare, nulla ipsum sagittis risus, nec cursus justo lacus vel sapien. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Quisque quis sem at ante posuere sodales non sit amet dolor. Mauris sagittis magna sed aliquam lacinia. Phasellus nec sapien maximus, fringilla urna a, commodo mauris.' }

      it 'returns "9034"' do
        expect(subject).to eq '9034'
      end
    end

    context 'when passed "Hello World"' do
      let(:data) { 'Hello World' }

      it 'returns "B2DA"' do
        expect(subject).to eq 'B2DA'
      end
    end

    context 'when passed "CSCS Data"' do
      let(:data) { 'CSCS Data' }

      it 'returns "9583"' do
        expect(subject).to eq '9583'
      end
    end

    context 'when passed "0123456789"' do
      let(:data) { '0123456789' }

      it 'returns "829E"' do
        expect(subject).to eq '829E'
      end
    end

    context 'when passed 2k_michael_knight.jpg' do
      let(:data) { File.read(File.join(Rails.root, 'spec', 'fixtures', '2k_michael_knight.jpg')) }

      it 'returns "5404"' do
        expect(subject).to eq '5404'
      end
    end

    context 'when passed 2k_lego_dude.jpg' do
      let(:data) { File.read(File.join(Rails.root, 'spec', 'fixtures', '2k_lego_dude.jpg')) }

      it 'returns "53005"' do
        expect(subject).to eq '53005'
      end
    end
  end
end

这是我编写的代码(它使用 digest-crc gem):

require 'digest/crc16_ccitt'

class ChecksumCalculator
  def self.call(data)
    crc = Digest::CRC16CCITT.new
    crc << data
    (crc.checksum ^ 0xffff).to_s(16).upcase
  end
end

但是虽然字符串的规格通过得很好,但图像却没有。

Failures:

    1) ChecksumCalculator.call when passed 2k_lego_dude.jpg returns "53005" Failure/Error: expect(subject).to eq '53005'

expected: "53005"
got: "CF0D"

(compared using ==)
# ./spec/lib/checksum_calculator_spec.rb:58:in `block (4 levels) in <top (required)>'
# -e:1:in `<main>'

    2) ChecksumCalculator.call when passed 2k_michael_knight.jpg returns "5404" Failure/Error: expect(subject).to eq '5404'

expected: "5404"
got: "151C"

(compared using ==)
# ./spec/lib/checksum_calculator_spec.rb:51:in `block (4 levels) in <top (required)>'
# -e:1:in `<main>'

我感觉代码运行良好,但我传递图像的方式有问题。有人可以帮忙吗?

供参考,图片如下:

谢谢

您的代码是正确的。测试用例错误。

出于某种原因,大多数测试用例与十六进制值进行比较,但两个 jpeg 文件与十进制值进行比较。十六进制的 CF0D 是十进制的 53005。十六进制的 151C 是十进制的 5404

直接线索是 53005 有五位数字,但 16 位十六进制值只能有四位。

顺便说一句,CRC 是 Genibus CRC-16。它既不是真也不是假的 CCITT CRC-16。参见 this catalog