diff options
Diffstat (limited to 'Compat.hs')
-rw-r--r-- | Compat.hs | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/Compat.hs b/Compat.hs new file mode 100644 index 0000000..43f62c0 --- /dev/null +++ b/Compat.hs | |||
@@ -0,0 +1,54 @@ | |||
1 | module Compat where | ||
2 | |||
3 | import Data.Bits | ||
4 | import Data.Word | ||
5 | import Data.ASN1.Types | ||
6 | import Data.ASN1.Encoding | ||
7 | import Data.ASN1.BinaryEncoding | ||
8 | import Crypto.PubKey.RSA as RSA | ||
9 | |||
10 | instance ASN1Object PublicKey where | ||
11 | toASN1 pubKey = \xs -> Start Sequence | ||
12 | : IntVal (public_n pubKey) | ||
13 | : IntVal (public_e pubKey) | ||
14 | : End Sequence | ||
15 | : xs | ||
16 | fromASN1 (Start Sequence:IntVal smodulus:IntVal pubexp:End Sequence:xs) = | ||
17 | Right (PublicKey { public_size = calculate_modulus modulus 1 | ||
18 | , public_n = modulus | ||
19 | , public_e = pubexp | ||
20 | } | ||
21 | , xs) | ||
22 | where calculate_modulus n i = if (2 ^ (i * 8)) > n then i else calculate_modulus n (i+1) | ||
23 | -- some bad implementation will not serialize ASN.1 integer properly, leading | ||
24 | -- to negative modulus. if that's the case, we correct it. | ||
25 | modulus = toPositive smodulus | ||
26 | fromASN1 ( Start Sequence | ||
27 | : IntVal 0 | ||
28 | : Start Sequence | ||
29 | : OID [1, 2, 840, 113549, 1, 1, 1] | ||
30 | : Null | ||
31 | : End Sequence | ||
32 | : OctetString bs | ||
33 | : xs | ||
34 | ) = let inner = either strError fromASN1 $ decodeASN1' BER bs | ||
35 | strError = Left . | ||
36 | ("fromASN1: RSA.PublicKey: " ++) . show | ||
37 | in either Left (\(k, _) -> Right (k, xs)) inner | ||
38 | fromASN1 _ = | ||
39 | Left "fromASN1: RSA.PublicKey: unexpected format" | ||
40 | |||
41 | |||
42 | toPositive :: Integer -> Integer | ||
43 | toPositive int | ||
44 | | int < 0 = uintOfBytes $ bytesOfInt int | ||
45 | | otherwise = int | ||
46 | where uintOfBytes = foldl (\acc n -> (acc `shiftL` 8) + fromIntegral n) 0 | ||
47 | bytesOfInt :: Integer -> [Word8] | ||
48 | bytesOfInt n = if testBit (head nints) 7 then nints else 0xff : nints | ||
49 | where nints = reverse $ plusOne $ reverse $ map complement $ bytesOfUInt (abs n) | ||
50 | plusOne [] = [1] | ||
51 | plusOne (x:xs) = if x == 0xff then 0 : plusOne xs else (x+1) : xs | ||
52 | bytesOfUInt x = reverse (list x) | ||
53 | where list i = if i <= 0xff then [fromIntegral i] else (fromIntegral i .&. 0xff) : list (i `shiftR` 8) | ||
54 | |||