summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoro <o@immerda.ch>2011-06-26 19:24:19 +0200
committero <o@immerda.ch>2011-06-26 19:24:19 +0200
commit9ad4dd3a722a0afdf6271a6ee90ce681ee644a38 (patch)
tree643354dc6e713244a535bbbe483146f18aada1e7
parent288bfcaa4d115da073650b0ea69dd24b1cc60cd7 (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.rb10
-rw-r--r--lib/fpg/io/zappable_byte_stream.rb54
-rw-r--r--lib/fpg/packets/public_subkey.rb2
-rw-r--r--lib/fpg/packets/secret_subkey.rb2
-rw-r--r--lib/fpg/parse/packet.rb27
-rw-r--r--lib/fpg/parse/public_key_encrypted_session_key.rb2
-rw-r--r--lib/fpg/parse/public_subkey.rb5
-rw-r--r--lib/fpg/parse/secret_subkey.rb5
-rw-r--r--lib/fpg/public_key_algos/algo.rb1
-rw-r--r--spec/zappable_byte_stream_spec.rb57
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
+