سؤال

ولدي الوضع حيث أريد أن إنشاء توقيع من بنية بيانات:

my $signature = ds_to_sig(
  { foo   => 'bar',
    baz   => 'bundy',
    boing => undef,
    number => 1_234_567,
  }
);

وينبغي أن يكون الهدف الذي إذا تغير بنية بيانات حتى ذلك الحين يجب التوقيع.

هل هناك طريقة ثابتة للقيام بذلك؟

هل كانت مفيدة؟

المحلول

وأفضل طريقة للقيام بذلك هو استخدام نظام التسلسل في أعماق بنية مثل <وأ href = "http://search.cpan.org/~ams/Storable-2.18/Storable.pm" يختلط = "noreferrer" > القابل للتخزين . سوف هيكلين مع نفس البيانات إنتاج نفس سائل الانتاج القابل للتخزين، بحيث يمكن مقارنة.

#!/usr/bin/perl

use strict;
use warnings;

use Storable ('freeze');

$Storable::canonical = 1;

my $one = { foo => 42, bar => [ 1, 2, 3 ] };
my $two = { foo => 42, bar => [ 1, 2, 3 ] };

my $one_s = freeze $one;
my $two_s = freeze $two;

print "match\n" if $one_s eq $two_s;

و... ولإثبات معكوس:

$one = [ 4, 5, 6 ];
$one_s = freeze $one;

print "no match" if $one_s ne $two_s;

نصائح أخرى

وأعتقد أن ما كنت تبحث عن وظيفة تجزئة. أوصي نهج مثل هذا:

use Storable;
$Storable::canonical = 1;
sub ds_to_sig {
    my $structure = shift;
    return hash(freeze $structure);
}

وتجزئة وظيفة يمكن أن يكون أي وظيفة التجزئة، على سبيل المثال MD5 وظيفة من دايجست :: MD5

استخدم القابل للتخزين :: nstore لتحويله إلى تمثيل ثنائي، ومن ثم حساب الاختباري (على سبيل المثال مع وحدة دايجست).

وحد سواء وحدات هي الوحدات الأساسية.

Digest::MD5->new->add(
  Data::Dumper->new([$structure])
   ->Purity(0)
   ->Terse(1)
   ->Indent(0)
   ->Useqq(1)
   ->Sortkeys(1)
   ->Dump()
)->b64digest();

وأعتقد أن الكلمة التي تبحث عنها هي "تجزئة" .

وأساسا، يمكنك وضع بنية البيانات الخاصة بك من خلال وظيفة التي تولد قيمة فريدة إلى حد ما من ذلك. ستكون هذه القيمة signiture الخاص بك.

لا يمكن استخدام كائن بدلا من البنية؟ وبهذه الطريقة يمكن أن نرى ما إذا كان الهدف من ذلك هو مثيل من نوع دون الحاجة إلى مقارنة التجزئة، الخ.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top