diff options
-rw-r--r-- | dht/cbits/crc4_itu.c | 44 | ||||
-rw-r--r-- | dht/src/Codec/AsciiKey256.hs | 47 |
2 files changed, 78 insertions, 13 deletions
diff --git a/dht/cbits/crc4_itu.c b/dht/cbits/crc4_itu.c new file mode 100644 index 00000000..8e3b0489 --- /dev/null +++ b/dht/cbits/crc4_itu.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /*----------------------------------------------------------------- | ||
2 | | crc4_itu.c | ||
3 | | | ||
4 | | CRC4-ITU library using lookup table method. | ||
5 | | | ||
6 | *-------------------------------------------------------------------*/ | ||
7 | |||
8 | #include <stddef.h> | ||
9 | |||
10 | static unsigned char const crc4itu_bbox[256] = { | ||
11 | 0x0, 0x7, 0xe, 0x9, 0x5, 0x2, 0xb, 0xc, 0xa, 0xd, 0x4, 0x3, 0xf, 0x8, 0x1, 0x6, | ||
12 | 0xd, 0xa, 0x3, 0x4, 0x8, 0xf, 0x6, 0x1, 0x7, 0x0, 0x9, 0xe, 0x2, 0x5, 0xc, 0xb, | ||
13 | 0x3, 0x4, 0xd, 0xa, 0x6, 0x1, 0x8, 0xf, 0x9, 0xe, 0x7, 0x0, 0xc, 0xb, 0x2, 0x5, | ||
14 | 0xe, 0x9, 0x0, 0x7, 0xb, 0xc, 0x5, 0x2, 0x4, 0x3, 0xa, 0xd, 0x1, 0x6, 0xf, 0x8, | ||
15 | 0x6, 0x1, 0x8, 0xf, 0x3, 0x4, 0xd, 0xa, 0xc, 0xb, 0x2, 0x5, 0x9, 0xe, 0x7, 0x0, | ||
16 | 0xb, 0xc, 0x5, 0x2, 0xe, 0x9, 0x0, 0x7, 0x1, 0x6, 0xf, 0x8, 0x4, 0x3, 0xa, 0xd, | ||
17 | 0x5, 0x2, 0xb, 0xc, 0x0, 0x7, 0xe, 0x9, 0xf, 0x8, 0x1, 0x6, 0xa, 0xd, 0x4, 0x3, | ||
18 | 0x8, 0xf, 0x6, 0x1, 0xd, 0xa, 0x3, 0x4, 0x2, 0x5, 0xc, 0xb, 0x7, 0x0, 0x9, 0xe, | ||
19 | 0xc, 0xb, 0x2, 0x5, 0x9, 0xe, 0x7, 0x0, 0x6, 0x1, 0x8, 0xf, 0x3, 0x4, 0xd, 0xa, | ||
20 | 0x1, 0x6, 0xf, 0x8, 0x4, 0x3, 0xa, 0xd, 0xb, 0xc, 0x5, 0x2, 0xe, 0x9, 0x0, 0x7, | ||
21 | 0xf, 0x8, 0x1, 0x6, 0xa, 0xd, 0x4, 0x3, 0x5, 0x2, 0xb, 0xc, 0x0, 0x7, 0xe, 0x9, | ||
22 | 0x2, 0x5, 0xc, 0xb, 0x7, 0x0, 0x9, 0xe, 0x8, 0xf, 0x6, 0x1, 0xd, 0xa, 0x3, 0x4, | ||
23 | 0xa, 0xd, 0x4, 0x3, 0xf, 0x8, 0x1, 0x6, 0x0, 0x7, 0xe, 0x9, 0x5, 0x2, 0xb, 0xc, | ||
24 | 0x7, 0x0, 0x9, 0xe, 0x2, 0x5, 0xc, 0xb, 0xd, 0xa, 0x3, 0x4, 0x8, 0xf, 0x6, 0x1, | ||
25 | 0x9, 0xe, 0x7, 0x0, 0xc, 0xb, 0x2, 0x5, 0x3, 0x4, 0xd, 0xa, 0x6, 0x1, 0x8, 0xf, | ||
26 | 0x4, 0x3, 0xa, 0xd, 0x1, 0x6, 0xf, 0x8, 0xe, 0x9, 0x0, 0x7, 0xb, 0xc, 0x5, 0x2 | ||
27 | }; | ||
28 | |||
29 | /** | ||
30 | * CRC4-ITU function | ||
31 | * | ||
32 | * Parameters: | ||
33 | * crc Existing CRC value (usually 0x00) before process a new one. | ||
34 | * data Pointer to data to be hashed with CRC | ||
35 | * len Size of data | ||
36 | * | ||
37 | * Returns: CRC value in lowest 4 bits. | ||
38 | */ | ||
39 | unsigned char crc4itu(unsigned char crc, unsigned char *data, unsigned int len) { | ||
40 | if (data == NULL) return 0; | ||
41 | crc &= 0xf; | ||
42 | while (len--) crc = crc4itu_bbox[crc ^ *data++]; | ||
43 | return crc; | ||
44 | } | ||
diff --git a/dht/src/Codec/AsciiKey256.hs b/dht/src/Codec/AsciiKey256.hs index 6040f454..ee17b7c1 100644 --- a/dht/src/Codec/AsciiKey256.hs +++ b/dht/src/Codec/AsciiKey256.hs | |||
@@ -3,6 +3,7 @@ module Codec.AsciiKey256 where | |||
3 | 3 | ||
4 | import Control.Applicative | 4 | import Control.Applicative |
5 | import Control.Monad | 5 | import Control.Monad |
6 | import Data.Bits | ||
6 | import qualified Data.ByteArray as BA | 7 | import qualified Data.ByteArray as BA |
7 | ;import Data.ByteArray as BA (ByteArrayAccess) | 8 | ;import Data.ByteArray as BA (ByteArrayAccess) |
8 | import qualified Data.ByteString as B | 9 | import qualified Data.ByteString as B |
@@ -17,6 +18,7 @@ import qualified Data.Text as T | |||
17 | ;import Data.Text (Text) | 18 | ;import Data.Text (Text) |
18 | import Data.Word | 19 | import Data.Word |
19 | import Foreign.Ptr | 20 | import Foreign.Ptr |
21 | import System.IO.Unsafe | ||
20 | import qualified Text.ParserCombinators.ReadP as RP | 22 | import qualified Text.ParserCombinators.ReadP as RP |
21 | 23 | ||
22 | stripSuffix :: Text -> Text -> Maybe Text | 24 | stripSuffix :: Text -> Text -> Maybe Text |
@@ -67,14 +69,33 @@ parseToken32 str = fmap (BA.drop 1) $ Base64.decode $ C8.pack $ 'A':map (nmtoken | |||
67 | showToken32 :: ByteArrayAccess bin => bin -> String | 69 | showToken32 :: ByteArrayAccess bin => bin -> String |
68 | showToken32 bs = map (nmtoken64 True) $ C8.unpack $ BA.drop 1 $ Base64.encode $ BA.cons 0 $ BA.convert bs | 70 | showToken32 bs = map (nmtoken64 True) $ C8.unpack $ BA.drop 1 $ Base64.encode $ BA.cons 0 $ BA.convert bs |
69 | 71 | ||
72 | foreign import ccall "crc4itu" c_crc4itu :: Word8 -- ^ init crc | ||
73 | -> Ptr Word8 -- ^ data to checksum | ||
74 | -> Int32 -- ^ length of data | ||
75 | -> IO Word8 -- crc in low 4 bits | ||
76 | |||
77 | -- | CRC4-ITU. Return crc in lowest 4 bits. | ||
78 | crc4itu :: ByteArrayAccess ba => Word8 -- ^ Existing CRC value (usually 0x00) before process a new one. | ||
79 | -> ba -- ^ Data to checksum. | ||
80 | -> Word8 | ||
81 | crc4itu crc0 b = unsafePerformIO $ BA.withByteArray b $ \p -> | ||
82 | c_crc4itu crc0 p (fromIntegral $ BA.length b) | ||
70 | 83 | ||
71 | -- | Parse 52-digit z-base32 token into 32-byte bytestring. | 84 | -- | Parse 52-digit z-base32 token into 32-byte bytestring. |
72 | parse32Token32 :: String -> Either String ByteString | 85 | parse32Token32 :: String -> Either String ByteString |
73 | parse32Token32 str = fmap (BA.drop 1) $ Base32.decode $ C8.pack $ 'y':map (fixupDigit32 . toLower) (take 52 str) | 86 | parse32Token32 str = do |
74 | 87 | bs <- Base32.decode $ C8.pack $ map (fixupDigit32 . toLower) (take 52 str) ++ "y" | |
75 | -- | Encode 62-digit z-base32 token from 32-byte bytestring. | 88 | case BA.splitAt 32 bs of |
89 | (key,mac) | crc4itu 0 key == shiftR (BA.index mac 0) 4 | ||
90 | -> Right key | ||
91 | _ -> Left "Failed cyclic redundancy check." | ||
92 | |||
93 | -- | Encode 52-digit z-base32 token from 32-byte bytestring. | ||
76 | show32Token32 :: ByteArrayAccess bin => bin -> String | 94 | show32Token32 :: ByteArrayAccess bin => bin -> String |
77 | show32Token32 bs = map (nmtoken64 True) $ C8.unpack $ BA.drop 1 $ Base32.encode $ BA.cons 0 $ BA.convert bs | 95 | show32Token32 bs = C8.unpack $ B.take 52 $ Base32.encode (b `B.snoc` shiftL crc 4) |
96 | where | ||
97 | b = BA.convert bs | ||
98 | crc = crc4itu 0 bs | ||
78 | 99 | ||
79 | 100 | ||
80 | readsPrecKey256 :: (ByteString -> Maybe a) -> [Char] -> [(a, [Char])] | 101 | readsPrecKey256 :: (ByteString -> Maybe a) -> [Char] -> [(a, [Char])] |
@@ -96,11 +117,11 @@ parseKey256 nidstr = do | |||
96 | let nidbs = C8.pack nidstr | 117 | let nidbs = C8.pack nidstr |
97 | (bs,_) = Base16.decode nidbs | 118 | (bs,_) = Base16.decode nidbs |
98 | enid = case C8.length nidbs of | 119 | enid = case C8.length nidbs of |
99 | 52 -> Base32.decode (C8.pack $ 'y' : map (fixupDigit32 . toLower) nidstr) | 120 | 52 -> parse32Token32 nidstr |
100 | 43 -> Base64.decode (C8.pack $ 'A' : map (nmtoken64 False) nidstr) | 121 | 43 -> parseToken32 nidstr |
101 | _ -> Left "Wrong size of key." | 122 | _ -> Left "Wrong size of key." |
102 | idbs <- (guard (B.length bs == 32) >> return bs) | 123 | idbs <- (guard (B.length bs == 32) >> return bs) |
103 | <|> either fail (return . B.drop 1) enid | 124 | <|> either fail return enid |
104 | return idbs | 125 | return idbs |
105 | 126 | ||
106 | readP_key256 :: RP.ReadP ByteString | 127 | readP_key256 :: RP.ReadP ByteString |
@@ -112,12 +133,12 @@ readP_key256 = do | |||
112 | ] | 133 | ] |
113 | let failure = fail "Bad key." | 134 | let failure = fail "Bad key." |
114 | case is64 of | 135 | case is64 of |
115 | 32 -> case Base32.decode $ C8.pack $ 'y' : map (fixupDigit32 . toLower) hexhash of | 136 | 32 -> case parse32Token32 hexhash of |
116 | Right bs | B.length bs - 1==32 -> return (BA.drop 1 bs) | 137 | Right bs -> return bs |
117 | _ -> failure | 138 | _ -> failure |
118 | 64 -> case Base64.decode $ C8.pack $ 'A' : map (nmtoken64 False) hexhash of | 139 | 64 -> case parseToken32 hexhash of |
119 | Right bs | B.length bs - 1==32 -> return (BA.drop 1 bs) | 140 | Right bs -> return bs |
120 | _ -> failure | 141 | _ -> failure |
121 | 16 -> case Base16.decode $ C8.pack hexhash of | 142 | 16 -> case Base16.decode $ C8.pack hexhash of |
122 | (bs,rem) | B.length bs == 32 && B.null rem -> return bs | 143 | (bs,rem) | B.length bs == 32 && B.null rem -> return bs |
123 | _ -> failure | 144 | _ -> failure |