diff options
author | o <o@immerda.ch> | 2011-06-26 19:24:19 +0200 |
---|---|---|
committer | o <o@immerda.ch> | 2011-06-26 19:24:19 +0200 |
commit | 9ad4dd3a722a0afdf6271a6ee90ce681ee644a38 (patch) | |
tree | 643354dc6e713244a535bbbe483146f18aada1e7 | |
parent | 288bfcaa4d115da073650b0ea69dd24b1cc60cd7 (diff) |
trying to implement a bytestream where we can remove bytes.
this will simplify the parsing since e.g. Packet can already determine
the size of itself while removeing all intermediate size headers. a
subclass can then just read from the stream without having to care abouth
headers or gaps in the data stream.
-rw-r--r-- | lib/fpg/id/key_id.rb | 10 | ||||
-rw-r--r-- | lib/fpg/io/zappable_byte_stream.rb | 54 | ||||
-rw-r--r-- | lib/fpg/packets/public_subkey.rb | 2 | ||||
-rw-r--r-- | lib/fpg/packets/secret_subkey.rb | 2 | ||||
-rw-r--r-- | lib/fpg/parse/packet.rb | 27 | ||||
-rw-r--r-- | lib/fpg/parse/public_key_encrypted_session_key.rb | 2 | ||||
-rw-r--r-- | lib/fpg/parse/public_subkey.rb | 5 | ||||
-rw-r--r-- | lib/fpg/parse/secret_subkey.rb | 5 | ||||
-rw-r--r-- | lib/fpg/public_key_algos/algo.rb | 1 | ||||
-rw-r--r-- | spec/zappable_byte_stream_spec.rb | 57 |
10 files changed, 144 insertions, 21 deletions
diff --git a/lib/fpg/id/key_id.rb b/lib/fpg/id/key_id.rb new file mode 100644 index 0000000..5913d1b --- /dev/null +++ b/lib/fpg/id/key_id.rb @@ -0,0 +1,10 @@ +module FPG + module Id + class KeyId + attr_accessor :key_id + def initialize(key_id) + self.key_id = key_id + end + end + end +end diff --git a/lib/fpg/io/zappable_byte_stream.rb b/lib/fpg/io/zappable_byte_stream.rb new file mode 100644 index 0000000..a80c82a --- /dev/null +++ b/lib/fpg/io/zappable_byte_stream.rb @@ -0,0 +1,54 @@ +module FPG + module Io + class ZappableByteStream + attr_accessor :io, :zapped + def initialize(io) + self.io = io + self.zapped = {} + end + def zap(n=1) + (1..n).each do |i| + self.zapped[io.pos-i] = true + end + end + def getbyte + ret = io.getbyte + skip_to_next_byte + ret + end + def read(n) + ret = "" + n.times do + ret << getbyte + end + ret + end + def rewind + io.rewind + skip_to_next_byte + end + def eof? + io.eof? + end + def pos=(pos) + skip = zapped.keys.select{ |p| p < pos }.size + io.pos= pos+skip + end + def pos + io.pos + end + def seek(n,wh) + raise 'only support relative positioning' unless wh == IO::SEEK_CUR + n.times do + io.seek(1,IO::SEEK_CUR) + skip_to_next_byte + end + end + + private + def skip_to_next_byte + io.readbyte while zapped[io.pos] + end + end + end +end diff --git a/lib/fpg/packets/public_subkey.rb b/lib/fpg/packets/public_subkey.rb index b369589..537c0bd 100644 --- a/lib/fpg/packets/public_subkey.rb +++ b/lib/fpg/packets/public_subkey.rb @@ -1,6 +1,6 @@ module FPG module Packets - class PublicSubkey < Packet + class PublicSubkey < PublicKey end end end diff --git a/lib/fpg/packets/secret_subkey.rb b/lib/fpg/packets/secret_subkey.rb index 1230a3d..e13ffeb 100644 --- a/lib/fpg/packets/secret_subkey.rb +++ b/lib/fpg/packets/secret_subkey.rb @@ -1,6 +1,6 @@ module FPG module Packets - class SecretSubkey < Packet + class SecretSubkey < SecretKey end end end diff --git a/lib/fpg/parse/packet.rb b/lib/fpg/parse/packet.rb index 4fd832b..f8590cd 100644 --- a/lib/fpg/parse/packet.rb +++ b/lib/fpg/parse/packet.rb @@ -27,7 +27,6 @@ module FPG current_pos = stream.pos+1 stream.seek(-2,IO::SEEK_CUR) 4.times do - puts packet_header?(stream.getbyte) if packet_header?(stream.getbyte) then raise "i expected a packet header but found none. it could to be off by #{current_pos-stream.pos}" end @@ -44,11 +43,19 @@ module FPG def parse(stream) self.stream = stream self.byte_size = self.partial_byte_size = packet_size - parse_content - while partial_length? do - self.byte_size += self.partial_byte_size = new_packet_size - parse_content + if partial_length? then + self.stream = ZappableByteStream.new(stream) + start = self.stream.pos + while partial_length? do + size = new_packet_size + self.partial_byte_size = size[:s] + self.byte_size += size[:s]-size[:h] + #remove the header packets from the stream => subclasses wont have to worry abouth this + self.stream.zap(size[:h]) + end + self.stream.pos= start end + parse_content return self end @@ -65,7 +72,7 @@ module FPG def packet_size header = stream.getbyte if new_packet?(header) - new_packet_size + new_packet_size()[:s] else tag = old_size_tag(header) old_packet_size(tag) @@ -74,11 +81,11 @@ module FPG def new_packet_size self.partial_length= false first = stream.getbyte - return first if first < 192 - return ((first-192)<<8)+stream.getbyte+192 if first < 224 - return (first+stream.read(3)).unpack("N")[0] if first == 255 + return { :s => first, :h => 1 } if first < 192 + return { :s => ((firs<t-192)<<8)+stream.getbyte+192, :h => 2 } if first < 224 + return { :s => (first+stream.read(3)).unpack("N")[0], :h => 4 } if first == 255 self.partial_length= true - return 1<<(first&0x1f) + return { :s => 1<<(first&0x1f), :h => 1 } end def old_packet_size(tag) return stream.getbyte if tag == 0 diff --git a/lib/fpg/parse/public_key_encrypted_session_key.rb b/lib/fpg/parse/public_key_encrypted_session_key.rb index cf30f9d..536a7fc 100644 --- a/lib/fpg/parse/public_key_encrypted_session_key.rb +++ b/lib/fpg/parse/public_key_encrypted_session_key.rb @@ -12,7 +12,7 @@ module FPG raise "PublicKeyEncryptedSessionKeyParser Version must be 3" if stream.getbyte != 3 end def parse_keyid - self.key_id= stream.read(8) + self.key_id= Id::KeyId.new(stream.read(8)) end def parse_public_key_algo self.encryption_algo= PublicKeyAlgos::Algo.with_tag(stream.getbyte) diff --git a/lib/fpg/parse/public_subkey.rb b/lib/fpg/parse/public_subkey.rb index acbe7ab..0661a48 100644 --- a/lib/fpg/parse/public_subkey.rb +++ b/lib/fpg/parse/public_subkey.rb @@ -1,13 +1,10 @@ module FPG module Parse - module PublicSubkeyParser - include PacketParser - end class PublicSubkey < Packets::PublicSubkey def self.tag 14 end - include PublicSubkeyParser + include PublicKeyParser end end end diff --git a/lib/fpg/parse/secret_subkey.rb b/lib/fpg/parse/secret_subkey.rb index 30724a2..ba2d04e 100644 --- a/lib/fpg/parse/secret_subkey.rb +++ b/lib/fpg/parse/secret_subkey.rb @@ -1,13 +1,10 @@ module FPG module Parse - module SecretSubkeyParser - include PacketParser - end class SecretSubkey < Packets::SecretSubkey def self.tag 7 end - include SecretSubkeyParser + include SecretKeyParser end end end diff --git a/lib/fpg/public_key_algos/algo.rb b/lib/fpg/public_key_algos/algo.rb index 03d28d0..b97b167 100644 --- a/lib/fpg/public_key_algos/algo.rb +++ b/lib/fpg/public_key_algos/algo.rb @@ -1,6 +1,7 @@ module FPG module PublicKeyAlgos class Algo + attr_accessor :key_material include TaggedSubclasses end end diff --git a/spec/zappable_byte_stream_spec.rb b/spec/zappable_byte_stream_spec.rb new file mode 100644 index 0000000..129fa75 --- /dev/null +++ b/spec/zappable_byte_stream_spec.rb @@ -0,0 +1,57 @@ +require File.join(File.dirname(__FILE__), %w[spec_helper]) + +require 'stringio' + +include FPG::Io + +describe ZappableByteStream do + before(:each) do + @stream = ZappableByteStream.new(StringIO.new("test123")) + end + + it "should behave like a normal stream" do + @stream.getbyte.should == "t".unpack("C1")[0] + @stream.read(3).should == "est" + @stream.read(3) + @stream.eof?.should be_true + end + it "should be able to zap a byte" do + @stream.read(3) + @stream.zap + @stream.rewind + @stream.read(3).should == "tet" + end + it "should be able to zap multiple bytes" do + @stream.read(5) + @stream.zap(3) + @stream.rewind + @stream.read(4).should == "te23" + end + it "should be able to detect eof even if on zapped byte" do + @stream.read(7) + @stream.zap(3) + @stream.rewind + @stream.read(4) + @stream.eof?.should be_true + end + it "should be able to rewind with zapped bytes at the beginning" do + @stream.read(2) + @stream.zap(2) + @stream.rewind + @stream.read(2).should == "st" + end + it "should be able to set the position in regard to zapped bytes" do + @stream.read(4) + @stream.zap(2) + @stream.pos=3 + @stream.read(2).should == "12" + end + it "should be able to seek in regard to zapped bytes" do + @stream.read(4) + @stream.zap(2) + @stream.pos=2 + @stream.seek(1,IO::SEEK_CUR) + @stream.read(2).should == "12" + end +end + |