cryptopp 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. data/.gitignore +8 -0
  2. data/MIT-LICENSE +22 -0
  3. data/README +7 -0
  4. data/Rakefile +42 -0
  5. data/cryptopp.gemspec +199 -0
  6. data/ext/.gitignore +5 -0
  7. data/ext/Rakefile +16 -0
  8. data/ext/ciphers.cpp +1402 -0
  9. data/ext/cryptopp.cpp +285 -0
  10. data/ext/cryptopp_ruby_api.h +139 -0
  11. data/ext/defs/block_modes.def +10 -0
  12. data/ext/defs/checksums.def +10 -0
  13. data/ext/defs/ciphers.def +136 -0
  14. data/ext/defs/hashes.def +78 -0
  15. data/ext/defs/hmacs.def +54 -0
  16. data/ext/defs/paddings.def +9 -0
  17. data/ext/defs/rngs.def +7 -0
  18. data/ext/digests.cpp +1120 -0
  19. data/ext/extconf.rb +39 -0
  20. data/ext/j3way.cpp +22 -0
  21. data/ext/j3way.h +29 -0
  22. data/ext/jadler32.h +32 -0
  23. data/ext/jaes.cpp +22 -0
  24. data/ext/jaes.h +31 -0
  25. data/ext/jarc4.cpp +22 -0
  26. data/ext/jarc4.h +37 -0
  27. data/ext/jbase.cpp +172 -0
  28. data/ext/jbase.h +92 -0
  29. data/ext/jbasiccipherinfo.h +74 -0
  30. data/ext/jblowfish.cpp +22 -0
  31. data/ext/jblowfish.h +29 -0
  32. data/ext/jcamellia.cpp +24 -0
  33. data/ext/jcamellia.h +33 -0
  34. data/ext/jcast128.cpp +22 -0
  35. data/ext/jcast128.h +31 -0
  36. data/ext/jcast256.cpp +22 -0
  37. data/ext/jcast256.h +31 -0
  38. data/ext/jcipher.cpp +112 -0
  39. data/ext/jcipher.h +42 -0
  40. data/ext/jcipher_t.h +469 -0
  41. data/ext/jconfig.h +127 -0
  42. data/ext/jconstants.h +189 -0
  43. data/ext/jcrc32.h +32 -0
  44. data/ext/jdes.cpp +22 -0
  45. data/ext/jdes.h +31 -0
  46. data/ext/jdes_ede2.cpp +22 -0
  47. data/ext/jdes_ede2.h +31 -0
  48. data/ext/jdes_ede3.cpp +22 -0
  49. data/ext/jdes_ede3.h +31 -0
  50. data/ext/jdes_xex3.cpp +22 -0
  51. data/ext/jdes_xex3.h +31 -0
  52. data/ext/jdiamond2.cpp +22 -0
  53. data/ext/jdiamond2.h +31 -0
  54. data/ext/jdiamond2lite.cpp +22 -0
  55. data/ext/jdiamond2lite.h +31 -0
  56. data/ext/jexception.h +20 -0
  57. data/ext/jgost.cpp +22 -0
  58. data/ext/jgost.h +31 -0
  59. data/ext/jhash.cpp +92 -0
  60. data/ext/jhash.h +54 -0
  61. data/ext/jhash_t.h +121 -0
  62. data/ext/jhaval.h +64 -0
  63. data/ext/jhelpers.cpp +90 -0
  64. data/ext/jhelpers.h +38 -0
  65. data/ext/jhmac.cpp +44 -0
  66. data/ext/jhmac.h +34 -0
  67. data/ext/jhmac_t.h +125 -0
  68. data/ext/jidea.cpp +22 -0
  69. data/ext/jidea.h +31 -0
  70. data/ext/jmarc4.cpp +22 -0
  71. data/ext/jmarc4.h +37 -0
  72. data/ext/jmars.cpp +22 -0
  73. data/ext/jmars.h +31 -0
  74. data/ext/jmd2.h +56 -0
  75. data/ext/jmd4.h +56 -0
  76. data/ext/jmd5.h +56 -0
  77. data/ext/jpanamacipher.cpp +32 -0
  78. data/ext/jpanamacipher.h +46 -0
  79. data/ext/jpanamahash.h +44 -0
  80. data/ext/jrc2.cpp +44 -0
  81. data/ext/jrc2.h +39 -0
  82. data/ext/jrc5.cpp +22 -0
  83. data/ext/jrc5.h +31 -0
  84. data/ext/jrc6.cpp +22 -0
  85. data/ext/jrc6.h +31 -0
  86. data/ext/jripemd160.h +113 -0
  87. data/ext/jsafer.cpp +32 -0
  88. data/ext/jsafer.h +42 -0
  89. data/ext/jseal.cpp +32 -0
  90. data/ext/jseal.h +42 -0
  91. data/ext/jserpent.cpp +22 -0
  92. data/ext/jserpent.h +31 -0
  93. data/ext/jsha.h +122 -0
  94. data/ext/jshacal2.cpp +22 -0
  95. data/ext/jshacal2.h +31 -0
  96. data/ext/jshark.cpp +24 -0
  97. data/ext/jshark.h +33 -0
  98. data/ext/jsink.cpp +90 -0
  99. data/ext/jsink.h +154 -0
  100. data/ext/jskipjack.cpp +22 -0
  101. data/ext/jskipjack.h +31 -0
  102. data/ext/jsquare.cpp +22 -0
  103. data/ext/jsquare.h +31 -0
  104. data/ext/jstream.cpp +8 -0
  105. data/ext/jstream.h +20 -0
  106. data/ext/jstream_t.h +175 -0
  107. data/ext/jtea.cpp +22 -0
  108. data/ext/jtea.h +31 -0
  109. data/ext/jtiger.h +52 -0
  110. data/ext/jtwofish.cpp +22 -0
  111. data/ext/jtwofish.h +31 -0
  112. data/ext/jwhirlpool.h +52 -0
  113. data/ext/utils.cpp +8 -0
  114. data/extras/parser_c.rb +114 -0
  115. data/test/ciphers_test.rb +37 -0
  116. data/test/data/ciphers/3desval.dat +7 -0
  117. data/test/data/ciphers/3wayval.dat +6 -0
  118. data/test/data/ciphers/arc4.dat +8 -0
  119. data/test/data/ciphers/blowfish.dat +5 -0
  120. data/test/data/ciphers/camellia.dat +7 -0
  121. data/test/data/ciphers/cast128v.dat +5 -0
  122. data/test/data/ciphers/cast256v.dat +5 -0
  123. data/test/data/ciphers/descert.dat +198 -0
  124. data/test/data/ciphers/diamond.dat +9 -0
  125. data/test/data/ciphers/gostval.dat +10 -0
  126. data/test/data/ciphers/ideaval.dat +13 -0
  127. data/test/data/ciphers/marsval.dat +11 -0
  128. data/test/data/ciphers/panamac.dat +7 -0
  129. data/test/data/ciphers/rc2val.dat +10 -0
  130. data/test/data/ciphers/rc5val.dat +7 -0
  131. data/test/data/ciphers/rc6val.dat +8 -0
  132. data/test/data/ciphers/rijndael.dat +11 -0
  133. data/test/data/ciphers/saferval.dat +27 -0
  134. data/test/data/ciphers/seal.dat +3 -0
  135. data/test/data/ciphers/serpentv.dat +11 -0
  136. data/test/data/ciphers/shacal2.dat +7 -0
  137. data/test/data/ciphers/sharkval.dat +9 -0
  138. data/test/data/ciphers/skipjack.dat +3 -0
  139. data/test/data/ciphers/squareva.dat +10 -0
  140. data/test/data/ciphers/twofishv.dat +11 -0
  141. data/test/data/digests/adler32.dat +8 -0
  142. data/test/data/digests/crc32.dat +10 -0
  143. data/test/data/digests/haval.dat +4 -0
  144. data/test/data/digests/havalcer.dat +23 -0
  145. data/test/data/digests/md2.dat +9 -0
  146. data/test/data/digests/md4.dat +9 -0
  147. data/test/data/digests/md5.dat +9 -0
  148. data/test/data/digests/panamah.dat +8 -0
  149. data/test/data/digests/ripemd.dat +43 -0
  150. data/test/data/digests/sha.dat +19 -0
  151. data/test/data/digests/tiger.dat +11 -0
  152. data/test/data/digests/whirlpool.dat +13 -0
  153. data/test/data/hmacs/hmac.dat +6 -0
  154. data/test/digests_test.rb +29 -0
  155. data/test/hmacs_test.rb +38 -0
  156. data/test/test_helper.rb +42 -0
  157. metadata +220 -0
@@ -0,0 +1,78 @@
1
+ #if ENABLED_HAVAL_HASH || defined(HASH_ALGORITHM_X_FORCE)
2
+ HASH_ALGORITHM_X(HAVAL, HAVAL, JHAVAL, haval)
3
+ #endif
4
+
5
+ #if ENABLED_HAVAL3_HASH || defined(HASH_ALGORITHM_X_FORCE)
6
+ HASH_ALGORITHM_X(HAVAL3, HAVAL3, JHAVAL3, haval3)
7
+ #endif
8
+
9
+ #if ENABLED_HAVAL4_HASH || defined(HASH_ALGORITHM_X_FORCE)
10
+ HASH_ALGORITHM_X(HAVAL4, HAVAL4, JHAVAL4, haval4)
11
+ #endif
12
+
13
+ #if ENABLED_HAVAL5_HASH || defined(HASH_ALGORITHM_X_FORCE)
14
+ HASH_ALGORITHM_X(HAVAL5, HAVAL5, JHAVAL5, haval5)
15
+ #endif
16
+
17
+ #if ENABLED_MD2_HASH || defined(HASH_ALGORITHM_X_FORCE)
18
+ HASH_ALGORITHM_X(MD2, MD2, JMD2, md2)
19
+ #endif
20
+
21
+ #if ENABLED_MD4_HASH || defined(HASH_ALGORITHM_X_FORCE)
22
+ HASH_ALGORITHM_X(MD4, MD4, JMD4, md4)
23
+ #endif
24
+
25
+ #if ENABLED_MD5_HASH || defined(HASH_ALGORITHM_X_FORCE)
26
+ HASH_ALGORITHM_X(MD5, MD5, JMD5, md5)
27
+ #endif
28
+
29
+ #if ENABLED_PANAMA_LITTLE_ENDIAN_HASH || defined(HASH_ALGORITHM_X_FORCE)
30
+ HASH_ALGORITHM_X(PanamaHashLE, PANAMA_LITTLE_ENDIAN, JPanamaHashLE, panama_le)
31
+ #endif
32
+
33
+ #if ENABLED_PANAMA_BIG_ENDIAN_HASH || defined(HASH_ALGORITHM_X_FORCE)
34
+ HASH_ALGORITHM_X(PanamaHashBE, PANAMA_BIG_ENDIAN, JPanamaHashBE, panama_be)
35
+ #endif
36
+
37
+ #if ENABLED_RIPEMD128_HASH || defined(HASH_ALGORITHM_X_FORCE)
38
+ HASH_ALGORITHM_X(RIPEMD128, RIPEMD128, JRIPEMD128, ripemd128)
39
+ #endif
40
+
41
+ #if ENABLED_RIPEMD160_HASH || defined(HASH_ALGORITHM_X_FORCE)
42
+ HASH_ALGORITHM_X(RIPEMD160, RIPEMD160, JRIPEMD160, ripemd160)
43
+ #endif
44
+
45
+ #if ENABLED_RIPEMD256_HASH || defined(HASH_ALGORITHM_X_FORCE)
46
+ HASH_ALGORITHM_X(RIPEMD256, RIPEMD256, JRIPEMD256, ripemd256)
47
+ #endif
48
+
49
+ #if ENABLED_RIPEMD320_HASH || defined(HASH_ALGORITHM_X_FORCE)
50
+ HASH_ALGORITHM_X(RIPEMD320, RIPEMD320, JRIPEMD320, ripemd320)
51
+ #endif
52
+
53
+ #if ENABLED_SHA1_HASH || defined(HASH_ALGORITHM_X_FORCE)
54
+ HASH_ALGORITHM_X(SHA1, SHA1, JSHA1, sha1)
55
+ #endif
56
+
57
+ #if ENABLED_SHA256_HASH || defined(HASH_ALGORITHM_X_FORCE)
58
+ HASH_ALGORITHM_X(SHA256, SHA256, JSHA256, sha256)
59
+ #endif
60
+
61
+ #if ENABLED_SHA384_HASH || defined(HASH_ALGORITHM_X_FORCE)
62
+ HASH_ALGORITHM_X(SHA384, SHA384, JSHA384, sha384)
63
+ #endif
64
+
65
+ #if ENABLED_SHA512_HASH || defined(HASH_ALGORITHM_X_FORCE)
66
+ HASH_ALGORITHM_X(SHA512, SHA512, JSHA512, sha512)
67
+ #endif
68
+
69
+ #if ENABLED_TIGER_HASH || defined(HASH_ALGORITHM_X_FORCE)
70
+ HASH_ALGORITHM_X(Tiger, TIGER, JTiger, tiger)
71
+ #endif
72
+
73
+ #if ENABLED_WHIRLPOOL_HASH || defined(HASH_ALGORITHM_X_FORCE)
74
+ HASH_ALGORITHM_X(Whirlpool, WHIRLPOOL, JWhirlpool, whirlpool)
75
+ #endif
76
+
77
+ #undef HASH_ALGORITHM_X
78
+ #undef HASH_ALGORITHM_X_FORCE
@@ -0,0 +1,54 @@
1
+ #if ENABLED_MD2_HMAC || HMAC_ALGORITHM_X_FORCE
2
+ HMAC_ALGORITHM_X(MD2_HMAC, MD2, JMD2_HMAC, md2_hmac)
3
+ #endif
4
+
5
+ #if ENABLED_MD4_HMAC || HMAC_ALGORITHM_X_FORCE
6
+ HMAC_ALGORITHM_X(MD4_HMAC, MD4, JMD4_HMAC, md4_hmac)
7
+ #endif
8
+
9
+ #if ENABLED_MD5_HMAC || HMAC_ALGORITHM_X_FORCE
10
+ HMAC_ALGORITHM_X(MD5_HMAC, MD5, JMD5_HMAC, md5_hmac)
11
+ #endif
12
+
13
+ #if ENABLED_RIPEMD128_HMAC || HMAC_ALGORITHM_X_FORCE
14
+ HMAC_ALGORITHM_X(RIPEMD128_HMAC, RIPEMD128, JRIPEMD128_HMAC, ripemd128_hmac)
15
+ #endif
16
+
17
+ #if ENABLED_RIPEMD160_HMAC || HMAC_ALGORITHM_X_FORCE
18
+ HMAC_ALGORITHM_X(RIPEMD160_HMAC, RIPEMD160, JRIPEMD160_HMAC, ripemd160_hmac)
19
+ #endif
20
+
21
+ #if ENABLED_RIPEMD256_HMAC || HMAC_ALGORITHM_X_FORCE
22
+ HMAC_ALGORITHM_X(RIPEMD256_HMAC, RIPEMD256, JRIPEMD256_HMAC, ripemd256_hmac)
23
+ #endif
24
+
25
+ #if ENABLED_RIPEMD320_HMAC || HMAC_ALGORITHM_X_FORCE
26
+ HMAC_ALGORITHM_X(RIPEMD320_HMAC, RIPEMD320, JRIPEMD320_HMAC, ripemd320_hmac)
27
+ #endif
28
+
29
+ #if ENABLED_SHA1_HMAC || HMAC_ALGORITHM_X_FORCE
30
+ HMAC_ALGORITHM_X(SHA1_HMAC, SHA1, JSHA1_HMAC, sha1_hmac)
31
+ #endif
32
+
33
+ #if ENABLED_SHA256_HMAC || HMAC_ALGORITHM_X_FORCE
34
+ HMAC_ALGORITHM_X(SHA256_HMAC, SHA256, JSHA256_HMAC, sha256_hmac)
35
+ #endif
36
+
37
+ #if ENABLED_SHA384_HMAC || HMAC_ALGORITHM_X_FORCE
38
+ HMAC_ALGORITHM_X(SHA384_HMAC, SHA384, JSHA384_HMAC, sha384_hmac)
39
+ #endif
40
+
41
+ #if ENABLED_SHA512_HMAC || HMAC_ALGORITHM_X_FORCE
42
+ HMAC_ALGORITHM_X(SHA512_HMAC, SHA512, JSHA512_HMAC, sha512_hmac)
43
+ #endif
44
+
45
+ #if ENABLED_TIGER_HMAC || HMAC_ALGORITHM_X_FORCE
46
+ HMAC_ALGORITHM_X(Tiger_HMAC, TIGER, JTiger_HMAC, tiger_hmac)
47
+ #endif
48
+
49
+ #if ENABLED_WHIRLPOOL_HMAC || HMAC_ALGORITHM_X_FORCE
50
+ HMAC_ALGORITHM_X(Whirlpool_HMAC, WHIRLPOOL, JWhirlpool_HMAC, whirlpool_hmac)
51
+ #endif
52
+
53
+ #undef HMAC_ALGORITHM_X
54
+ #undef HMAC_ALGORITHM_X_FORCE
@@ -0,0 +1,9 @@
1
+
2
+ // a constant, a Symbol name
3
+ PADDING_X(NO, no)
4
+ PADDING_X(ZEROS, zeros)
5
+ PADDING_X(PKCS, pkcs)
6
+ PADDING_X(ONE_AND_ZEROS, one_and_zeros)
7
+ PADDING_X(DEFAULT, default)
8
+
9
+ #undef PADDING_X
@@ -0,0 +1,7 @@
1
+
2
+ // constant, Symbol
3
+ RNG_X(NON_BLOCKING, non_blocking)
4
+ RNG_X(BLOCKING, blocking)
5
+ RNG_X(RAND, rand)
6
+
7
+ #undef RNG_X
@@ -0,0 +1,1120 @@
1
+
2
+ /*
3
+ * Copyright (c) 2002-2010 J Smith <dark.panda@gmail.com>
4
+ * Crypto++ copyright (c) 1995-2010 Wei Dai
5
+ * See COPYING for the extact license
6
+ */
7
+
8
+ // hash algorithms:
9
+
10
+ #include "jadler32.h"
11
+ #include "jcrc32.h"
12
+ #include "jhaval.h"
13
+ #include "jmd2.h"
14
+ #include "jmd4.h"
15
+ #include "jmd5.h"
16
+ #include "jpanamahash.h"
17
+ #include "jripemd160.h"
18
+ #include "jsha.h"
19
+ #include "jtiger.h"
20
+ #include "jwhirlpool.h"
21
+
22
+ #include "jexception.h"
23
+
24
+ #include "cryptopp_ruby_api.h"
25
+
26
+ extern void hash_mark(JHash *c);
27
+ extern void hash_free(JHash *c);
28
+
29
+ // forward declarations
30
+
31
+ static HashEnum digest_sym_to_const(VALUE hash);
32
+ static bool digest_enabled(HashEnum hash);
33
+ static void digest_options(VALUE self, VALUE options);
34
+ static JHash* digest_factory(VALUE algorithm);
35
+ static VALUE wrap_digest_in_ruby(JHash* hash);
36
+ static string digest_digest(VALUE self, bool hex);
37
+ static string digest_plaintext(VALUE self, bool hex);
38
+ static string digest_plaintext_eq(VALUE self, VALUE plaintext, bool hex);
39
+ static string digest_calculate(VALUE self, bool hex);
40
+ static string digest_digest_eq(VALUE self, VALUE digest, bool hex);
41
+ static string module_digest(int argc, VALUE *argv, VALUE self, bool hex);
42
+ static string module_digest_io(int argc, VALUE *argv, VALUE self, bool hex);
43
+ static string digest_digest_io(VALUE self, VALUE io, bool hex);
44
+ static void digest_hmac_options(VALUE self, VALUE options);
45
+ static string digest_hmac_key_eq(VALUE self, VALUE key, bool hex);
46
+ static string digest_hmac_key(VALUE self, bool hex);
47
+ static string module_hmac_digest(int argc, VALUE *argv, VALUE self, bool hex);
48
+
49
+ static HashEnum digest_sym_to_const(VALUE c)
50
+ {
51
+ HashEnum hash = UNKNOWN_HASH;
52
+ ID id = SYM2ID(c);
53
+
54
+ if (id == rb_intern("panama")) {
55
+ hash = PANAMA_HASH;
56
+ }
57
+ else if (id == rb_intern("sha")) {
58
+ hash = SHA1_HASH;
59
+ }
60
+ else if (id == rb_intern("sha_hmac")) {
61
+ hash = SHA1_HMAC;
62
+ }
63
+ # define CHECKSUM_ALGORITHM_X_FORCE 1
64
+ # define CHECKSUM_ALGORITHM_X(klass, r, c, s) \
65
+ else if (id == rb_intern(# s)) { \
66
+ hash = r ## _CHECKSUM; \
67
+ }
68
+ # include "defs/checksums.def"
69
+
70
+ # define HASH_ALGORITHM_X_FORCE 1
71
+ # define HASH_ALGORITHM_X(klass, r, c, s) \
72
+ else if (id == rb_intern(# s)) { \
73
+ hash = r ## _HASH; \
74
+ }
75
+ # include "defs/hashes.def"
76
+
77
+ # define HMAC_ALGORITHM_X_FORCE 1
78
+ # define HMAC_ALGORITHM_X(klass, r, c, s) \
79
+ else if (id == rb_intern(# s)) { \
80
+ hash = r ## _HMAC; \
81
+ }
82
+ # include "defs/hmacs.def"
83
+ return hash;
84
+ }
85
+
86
+
87
+ /* See if a hash algorithm is enabled. */
88
+ static bool digest_enabled(HashEnum hash)
89
+ {
90
+ switch (hash) {
91
+ # define CHECKSUM_ALGORITHM_X(klass, r, c, s) \
92
+ case r ##_CHECKSUM:
93
+ # include "defs/checksums.def"
94
+
95
+ # define HASH_ALGORITHM_X(klass, r, c, s) \
96
+ case r ##_HASH:
97
+ # include "defs/hashes.def"
98
+
99
+ # define HMAC_ALGORITHM_X(klass, r, c, s) \
100
+ case r ##_HMAC:
101
+ # include "defs/hmacs.def"
102
+ return true;
103
+ }
104
+ return false;
105
+ }
106
+
107
+
108
+ /* Figure out options for a digest. */
109
+ static void digest_options(VALUE self, VALUE options)
110
+ {
111
+ Check_Type(options, T_HASH);
112
+
113
+ {
114
+ VALUE plaintext = rb_hash_aref(options, ID2SYM(rb_intern("plaintext")));
115
+ VALUE plaintext_hex = rb_hash_aref(options, ID2SYM(rb_intern("plaintext_hex")));
116
+ if (!NIL_P(plaintext) && !NIL_P(plaintext_hex)) {
117
+ rb_raise(rb_eCryptoPP_Error, "can't set both plaintext and plaintext_hex in options");
118
+ }
119
+ else if (!NIL_P(plaintext)) {
120
+ digest_plaintext_eq(self, plaintext, false);
121
+ }
122
+ else if (!NIL_P(plaintext_hex)) {
123
+ digest_plaintext_eq(self, plaintext_hex, true);
124
+ }
125
+ }
126
+
127
+ {
128
+ VALUE digest = rb_hash_aref(options, ID2SYM(rb_intern("digest")));
129
+ VALUE digest_hex = rb_hash_aref(options, ID2SYM(rb_intern("digest_hex")));
130
+ if (!NIL_P(digest) && !NIL_P(digest_hex)) {
131
+ rb_raise(rb_eCryptoPP_Error, "can't set both digest and digest_hex in options");
132
+ }
133
+ else if (!NIL_P(digest)) {
134
+ digest_digest_eq(self, digest, false);
135
+ }
136
+ else if (!NIL_P(digest_hex)) {
137
+ digest_digest_eq(self, digest_hex, true);
138
+ }
139
+ }
140
+ }
141
+
142
+
143
+ /* Creates a new Digest object. */
144
+ static JHash* digest_factory(VALUE algorithm)
145
+ {
146
+ try {
147
+ switch (digest_sym_to_const(algorithm)) {
148
+ default:
149
+ throw JException("the requested algorithm cannot be found");
150
+ break;
151
+
152
+ # define CHECKSUM_ALGORITHM_X(klass, r, c, s) \
153
+ case r ## _CHECKSUM: \
154
+ return static_cast<c*>(new c);
155
+ # include "defs/checksums.def"
156
+
157
+ # define HASH_ALGORITHM_X(klass, r, c, s) \
158
+ case r ## _HASH: \
159
+ return static_cast<c*>(new c);
160
+ # include "defs/hashes.def"
161
+
162
+ # define HMAC_ALGORITHM_X(klass, r, c, s) \
163
+ case r ## _HMAC: \
164
+ return static_cast<c*>(new c);
165
+ # include "defs/hmacs.def"
166
+ }
167
+ }
168
+ catch (Exception& e) {
169
+ throw JException("Crypto++ exception: " + e.GetWhat());
170
+ }
171
+ }
172
+
173
+ /* Wraps a Digest/HMAC object into a Ruby object. May throw a JException if no
174
+ * suitable algorithm is found. */
175
+ static VALUE wrap_digest_in_ruby(JHash* hash)
176
+ {
177
+ const type_info& info = typeid(*hash);
178
+ # define CHECKSUM_ALGORITHM_X(klass, r, c, s) \
179
+ if (info == typeid(c)) { \
180
+ return Data_Wrap_Struct(rb_cCryptoPP_Digest_## r, hash_mark, hash_free, hash); \
181
+ } \
182
+ else
183
+ # include "defs/checksums.def"
184
+
185
+ # define HASH_ALGORITHM_X(klass, r, c, s) \
186
+ if (info == typeid(c)) { \
187
+ return Data_Wrap_Struct(rb_cCryptoPP_Digest_## r, hash_mark, hash_free, hash); \
188
+ } \
189
+ else
190
+ # include "defs/hashes.def"
191
+
192
+ # define HMAC_ALGORITHM_X(klass, r, c, s) \
193
+ if (info == typeid(c)) { \
194
+ return Data_Wrap_Struct(rb_cCryptoPP_Digest_HMAC_## r, hash_mark, hash_free, hash); \
195
+ } \
196
+ else
197
+ # include "defs/hmacs.def"
198
+ {
199
+ throw JException("the requested algorithm has been disabled");
200
+ }
201
+ }
202
+
203
+ /**
204
+ * call-seq:
205
+ * digest_factory(algorithm) => CryptoPP::Digest
206
+ * digest_factory(algorithm, plaintext) => CryptoPP::Digest
207
+ * digest_factory(algorithm, options) => CryptoPP::Digest
208
+ *
209
+ * Creates a new Digest object.
210
+ *
211
+ * See the Digest class for available options.
212
+ */
213
+ VALUE rb_module_digest_factory(int argc, VALUE *argv, VALUE self)
214
+ {
215
+ JHash* hash = NULL;
216
+ VALUE algorithm, options, retval;
217
+
218
+ rb_scan_args(argc, argv, "11", &algorithm, &options);
219
+ {
220
+ HashEnum a = digest_sym_to_const(algorithm);
221
+ if (!IS_NON_HMAC(a)) {
222
+ rb_raise(rb_eCryptoPP_Error, "invalid digest algorithm");
223
+ }
224
+ else {
225
+ try {
226
+ hash = digest_factory(algorithm);
227
+ retval = wrap_digest_in_ruby(hash);
228
+ }
229
+ catch (Exception& e) {
230
+ if (hash != NULL) {
231
+ delete hash;
232
+ }
233
+ rb_raise(rb_eCryptoPP_Error, e.GetWhat().c_str());
234
+ }
235
+ if (argc == 2) {
236
+ if (TYPE(options) == T_STRING) {
237
+ rb_digest_plaintext_eq(retval, options);
238
+ hash->hash();
239
+ }
240
+ else {
241
+ digest_options(retval, options);
242
+ }
243
+ }
244
+ return retval;
245
+ }
246
+ }
247
+ }
248
+
249
+ #define CHECKSUM_ALGORITHM_X(klass, r, n, s) \
250
+ VALUE rb_digest_ ## r ##_new(int argc, VALUE *argv, VALUE self) \
251
+ { \
252
+ VALUE options, retval; \
253
+ JHash* hash = NULL; \
254
+ try { \
255
+ hash = digest_factory(ID2SYM(rb_intern(# s))); \
256
+ retval = wrap_digest_in_ruby(hash); \
257
+ } \
258
+ catch (Exception& e) { \
259
+ if (hash != NULL) { \
260
+ delete hash; \
261
+ } \
262
+ rb_raise(rb_eCryptoPP_Error, e.GetWhat().c_str()); \
263
+ } \
264
+ rb_scan_args(argc, argv, "01", &options); \
265
+ if (!NIL_P(options)) { \
266
+ if (TYPE(options) == T_STRING) { \
267
+ rb_digest_plaintext_eq(retval, options); \
268
+ hash->hash(); \
269
+ } \
270
+ else { \
271
+ digest_options(retval, options); \
272
+ } \
273
+ } \
274
+ return retval; \
275
+ }
276
+ #include "defs/checksums.def"
277
+
278
+ #define HASH_ALGORITHM_X(klass, r, n, s) \
279
+ VALUE rb_digest_ ## r ##_new(int argc, VALUE *argv, VALUE self) \
280
+ { \
281
+ VALUE options, retval; \
282
+ JHash* hash = NULL; \
283
+ try { \
284
+ hash = digest_factory(ID2SYM(rb_intern(# s))); \
285
+ retval = wrap_digest_in_ruby(hash); \
286
+ } \
287
+ catch (Exception& e) { \
288
+ if (hash != NULL) { \
289
+ delete hash; \
290
+ } \
291
+ rb_raise(rb_eCryptoPP_Error, e.GetWhat().c_str()); \
292
+ } \
293
+ rb_scan_args(argc, argv, "01", &options); \
294
+ if (!NIL_P(options)) { \
295
+ if (TYPE(options) == T_STRING) { \
296
+ rb_digest_plaintext_eq(retval, options); \
297
+ hash->hash(); \
298
+ } \
299
+ else { \
300
+ digest_options(retval, options); \
301
+ } \
302
+ } \
303
+ return retval; \
304
+ }
305
+ #include "defs/hashes.def"
306
+
307
+
308
+ /**
309
+ * call-seq:
310
+ * update(plaintext) => String
311
+ *
312
+ * Updates the plaintext on a Digest and returns the new digested text.
313
+ */
314
+ VALUE rb_digest_update(VALUE self, VALUE plaintext)
315
+ {
316
+ JHash *hash = NULL;
317
+ Check_Type(plaintext, T_STRING);
318
+ Data_Get_Struct(self, JHash, hash);
319
+ hash->updatePlaintext(string(StringValuePtr(plaintext), RSTRING(plaintext)->len));
320
+ hash->hash();
321
+ return rb_tainted_str_new(hash->getHashtext().data(), hash->getHashtext().length());
322
+ }
323
+
324
+
325
+ /* Returns the digested text. */
326
+ static string digest_digest(VALUE self, bool hex)
327
+ {
328
+ JHash *hash = NULL;
329
+ Data_Get_Struct(self, JHash, hash);
330
+ return hash->getHashtext(hex);
331
+ }
332
+
333
+ /**
334
+ * call-seq:
335
+ * digest => String
336
+ *
337
+ * Returns the digested text in binary.
338
+ */
339
+ VALUE rb_digest_digest(VALUE self)
340
+ {
341
+ string retval = digest_digest(self, false);
342
+ return rb_tainted_str_new(retval.data(), retval.length());
343
+ }
344
+
345
+ /**
346
+ * call-seq:
347
+ * digest_hex => String
348
+ *
349
+ * Returns the digested text in hex.
350
+ */
351
+ VALUE rb_digest_digest_hex(VALUE self)
352
+ {
353
+ string retval = digest_digest(self, true);
354
+ return rb_tainted_str_new(retval.data(), retval.length());
355
+ }
356
+
357
+
358
+ /* Gets the plaintext from a hash. */
359
+ static string digest_plaintext(VALUE self, bool hex)
360
+ {
361
+ JHash *hash = NULL;
362
+ Data_Get_Struct(self, JHash, hash);
363
+ return hash->getPlaintext(hex);;
364
+ }
365
+
366
+ /**
367
+ * call-seq:
368
+ * plaintext => String
369
+ *
370
+ * Returns the plaintext used to generate the digest in binary.
371
+ */
372
+ VALUE rb_digest_plaintext(VALUE self)
373
+ {
374
+ string retval = digest_plaintext(self, false);
375
+ return rb_tainted_str_new(retval.data(), retval.length());
376
+ }
377
+
378
+ /**
379
+ * call-seq:
380
+ * plaintext_hex => String
381
+ *
382
+ * Returns the plaintext used to generate the digest in hex.
383
+ */
384
+ VALUE rb_digest_plaintext_hex(VALUE self)
385
+ {
386
+ string retval = digest_plaintext(self, true);
387
+ return rb_tainted_str_new(retval.data(), retval.length());
388
+ }
389
+
390
+
391
+ /* Sets the plaintext on a digest. */
392
+ static string digest_plaintext_eq(VALUE self, VALUE plaintext, bool hex)
393
+ {
394
+ JHash *hash = NULL;
395
+ Check_Type(plaintext, T_STRING);
396
+ Data_Get_Struct(self, JHash, hash);
397
+ hash->setPlaintext(string(StringValuePtr(plaintext), RSTRING(plaintext)->len), hex);
398
+ return hash->getPlaintext(hex);
399
+ }
400
+
401
+ /**
402
+ * call-seq:
403
+ * plaintext=(plaintext)
404
+ *
405
+ * Sets the plaintext on a Digest in binary.
406
+ */
407
+ VALUE rb_digest_plaintext_eq(VALUE self, VALUE plaintext)
408
+ {
409
+ digest_plaintext_eq(self, plaintext, false);
410
+ return plaintext;
411
+ }
412
+
413
+ /**
414
+ * call-seq:
415
+ * plaintext=(plaintext)
416
+ *
417
+ * Sets the plaintext on a Digest in hex.
418
+ */
419
+ VALUE rb_digest_plaintext_hex_eq(VALUE self, VALUE plaintext)
420
+ {
421
+ digest_plaintext_eq(self, plaintext, true);
422
+ return plaintext;
423
+ }
424
+
425
+
426
+ /* Calculates the digest. */
427
+ static string digest_calculate(VALUE self, bool hex)
428
+ {
429
+ JHash *hash = NULL;
430
+ Data_Get_Struct(self, JHash, hash);
431
+ hash->hash();
432
+ return hash->getHashtext(hex);
433
+ }
434
+
435
+ /**
436
+ * call-seq:
437
+ * calculate => String
438
+ *
439
+ * Calculates the digest and returns the result in binary.
440
+ */
441
+ VALUE rb_digest_calculate(VALUE self)
442
+ {
443
+ string retval = digest_calculate(self, false);
444
+ return rb_tainted_str_new(retval.data(), retval.length());
445
+ }
446
+
447
+ /**
448
+ * call-seq:
449
+ * calculate_hex => String
450
+ *
451
+ * Calculates the digest and returns the result in hex.
452
+ */
453
+ VALUE rb_digest_calculate_hex(VALUE self)
454
+ {
455
+ string retval = digest_calculate(self, true);
456
+ return rb_tainted_str_new(retval.data(), retval.length());
457
+ }
458
+
459
+
460
+ /* Sets the hashtext on a digest. */
461
+ static string digest_digest_eq(VALUE self, VALUE digest, bool hex)
462
+ {
463
+ JHash *hash = NULL;
464
+ Check_Type(digest, T_STRING);
465
+ Data_Get_Struct(self, JHash, hash);
466
+ hash->setHashtext(string(StringValuePtr(digest), RSTRING(digest)->len), hex);
467
+ return hash->getHashtext(hex);
468
+ }
469
+
470
+ /**
471
+ * call-seq:
472
+ * digest=(bin)
473
+ *
474
+ * Sets the digest text on a Digest in binary.
475
+ */
476
+ VALUE rb_digest_digest_eq(VALUE self, VALUE digest)
477
+ {
478
+ digest_digest_eq(self, digest, false);
479
+ return digest;
480
+ }
481
+
482
+ /**
483
+ * call-seq:
484
+ * digest_hex=(hex)
485
+ *
486
+ * Sets the digest text on a Digest in hex.
487
+ */
488
+ VALUE rb_digest_digest_hex_eq(VALUE self, VALUE digest)
489
+ {
490
+ digest_digest_eq(self, digest, true);
491
+ return digest;
492
+ }
493
+
494
+
495
+ /**
496
+ * call-seq:
497
+ * inspect => String
498
+ *
499
+ * Inspect method.
500
+ */
501
+ VALUE rb_digest_inspect(VALUE self)
502
+ {
503
+ JHash* hash = NULL;
504
+ string retval;
505
+ string cname = rb_obj_classname(self);
506
+ Data_Get_Struct(self, JHash, hash);
507
+ retval = "#<" + cname + ": " + hash->getHashtext(true) + ">";
508
+ return rb_str_new(retval.c_str(), retval.length());
509
+ }
510
+
511
+
512
+ /**
513
+ * Compares a Digest directly to a String. We'll attempt to detect whether or
514
+ * not the String is in binary or hex based on the number of characters in
515
+ * it -- if it's exactly double the expected number of bytes, then we'll
516
+ * assume we've got a hex String.
517
+ */
518
+ VALUE rb_digest_equals(VALUE self, VALUE compare)
519
+ {
520
+ JHash *hash = NULL;
521
+ VALUE str1, str2;
522
+ Check_Type(compare, T_STRING);
523
+ Data_Get_Struct(self, JHash, hash);
524
+ if (RSTRING(compare)->len == ((long) hash->getDigestSize() / 2)) {
525
+ str1 = rb_str_new(hash->getHashtext(false).data(), hash->getHashtext(false).length());
526
+ str2 = compare;
527
+ }
528
+ else if (RSTRING(compare)->len == ((long) hash->getDigestSize())) {
529
+ str1 = rb_str_new(hash->getHashtext(true).data(), hash->getHashtext(true).length());
530
+ str2 = rb_funcall(compare, rb_intern("downcase"), 0);
531
+ }
532
+ else {
533
+ rb_raise(rb_eCryptoPP_Error, "expected %d bytes, got %d", hash->getDigestSize() / 2, RSTRING(compare)->len);
534
+ }
535
+
536
+ if (rb_str_cmp(str1, str2) == 0) {
537
+ return Qtrue;
538
+ }
539
+ else {
540
+ return Qfalse;
541
+ }
542
+ }
543
+
544
+
545
+ /* Singleton method for digesting good stuff. */
546
+ static string module_digest(int argc, VALUE *argv, VALUE self, bool hex)
547
+ {
548
+ JHash* hash = NULL;
549
+ VALUE algorithm, plaintext, key;
550
+ if (argc < 2) {
551
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
552
+ }
553
+
554
+ if (IS_HMAC(digest_sym_to_const(argv[0]))) {
555
+ rb_scan_args(argc, argv, "21", &algorithm, &plaintext, &key);
556
+ Check_Type(plaintext, T_STRING);
557
+ Check_Type(key, T_STRING);
558
+ }
559
+ else {
560
+ rb_scan_args(argc, argv, "2", &algorithm, &plaintext);
561
+ Check_Type(plaintext, T_STRING);
562
+ }
563
+
564
+ try {
565
+ string retval;
566
+ hash = digest_factory(algorithm);
567
+ hash->setPlaintext(string(StringValuePtr(plaintext), RSTRING(plaintext)->len));
568
+ if (IS_HMAC(digest_sym_to_const(algorithm))) {
569
+ ((JHMAC*) hash)->setKey(string(StringValuePtr(key), RSTRING(key)->len));
570
+ }
571
+ hash->hash();
572
+ retval = hash->getHashtext(hex);
573
+
574
+ delete hash;
575
+ return retval;
576
+ }
577
+ catch (Exception& e) {
578
+ if (hash != NULL) {
579
+ delete hash;
580
+ }
581
+ rb_raise(rb_eCryptoPP_Error, e.GetWhat().c_str());
582
+ }
583
+ }
584
+
585
+ /**
586
+ * call-seq:
587
+ * digest(algorithm, plaintext) => String
588
+ *
589
+ * Digest the plaintext and returns the result in binary.
590
+ */
591
+ VALUE rb_module_digest(int argc, VALUE *argv, VALUE self)
592
+ {
593
+ string retval = module_digest(argc, argv, self, false);
594
+ return rb_tainted_str_new(retval.data(), retval.length());
595
+ }
596
+
597
+ /**
598
+ * call-seq:
599
+ * digest_hex(algorithm, plaintext) => String
600
+ *
601
+ * Digest the plaintext and returns the result in hex.
602
+ */
603
+ VALUE rb_module_digest_hex(int argc, VALUE *argv, VALUE self)
604
+ {
605
+ string retval = module_digest(argc, argv, self, true);
606
+ return rb_tainted_str_new(retval.data(), retval.length());
607
+ }
608
+
609
+
610
+ /* Digests an appropriate Ruby IO object. */
611
+ static string module_digest_io(int argc, VALUE *argv, VALUE self, bool hex)
612
+ {
613
+ JHash* hash = NULL;
614
+ VALUE algorithm, io;
615
+
616
+ rb_scan_args(argc, argv, "2", &algorithm, &io);
617
+ try {
618
+ string retval;
619
+ hash = digest_factory(algorithm);
620
+ retval = hash->hashRubyIO(&io, hex);
621
+
622
+ delete hash;
623
+ return retval;
624
+ }
625
+ catch (Exception& e) {
626
+ if (hash != NULL) {
627
+ delete hash;
628
+ }
629
+ rb_raise(rb_eCryptoPP_Error, e.GetWhat().c_str());
630
+ }
631
+ }
632
+
633
+ /**
634
+ * call-seq:
635
+ * digest_io(io) => String
636
+ *
637
+ * Digests a Ruby IO object and spits out the result in binary. You can use
638
+ * any sort of Ruby object as long as it implements <tt>eof?</tt>,
639
+ * <tt>read</tt>, <tt>write</tt> and <tt>flush</tt>.
640
+ *
641
+ * Example:
642
+ *
643
+ * cipher.digest_io(File.open("http://example.com/"))
644
+ */
645
+ VALUE rb_module_digest_io(int argc, VALUE *argv, VALUE self)
646
+ {
647
+ string retval = module_digest_io(argc, argv, self, false);
648
+ return rb_tainted_str_new(retval.data(), retval.length());
649
+ }
650
+
651
+ /**
652
+ * call-seq:
653
+ * digest_io_hex(io) => String
654
+ *
655
+ * Digests a Ruby IO object and spits out the result in hex. You can use
656
+ * any sort of Ruby object as long as it implements <tt>eof?</tt>,
657
+ * <tt>read</tt>, <tt>write</tt> and <tt>flush</tt>.
658
+ *
659
+ * Example:
660
+ *
661
+ * cipher.digest_io_hex(File.open("http://example.com/"))
662
+ */
663
+ VALUE rb_module_digest_io_hex(int argc, VALUE *argv, VALUE self)
664
+ {
665
+ string retval = module_digest_io(argc, argv, self, true);
666
+ return rb_tainted_str_new(retval.data(), retval.length());
667
+ }
668
+
669
+
670
+ /**
671
+ * call-seq:
672
+ * digest_enabled? => Boolean
673
+ *
674
+ * Is a Digest/HMAC algorithm available?
675
+ */
676
+ VALUE rb_module_digest_enabled(VALUE self, VALUE d)
677
+ {
678
+ if (digest_enabled(digest_sym_to_const(d))) {
679
+ return Qtrue;
680
+ }
681
+ else {
682
+ return Qfalse;
683
+ }
684
+ }
685
+
686
+
687
+ /* Returns the name of a hash algorithm. */
688
+ VALUE rb_module_digest_name(VALUE self, VALUE h)
689
+ {
690
+ switch ((enum HashEnum) NUM2INT(h)) {
691
+ default:
692
+ rb_raise(rb_eCryptoPP_Error, "could not find a valid digest type");
693
+ break;
694
+
695
+ # define CHECKSUM_ALGORITHM_X(klass, r, c, s) \
696
+ case r ## _CHECKSUM: \
697
+ return rb_tainted_str_new2(c::getHashName().c_str());
698
+ # include "defs/checksums.def"
699
+
700
+ # define HASH_ALGORITHM_X(klass, r, c, s) \
701
+ case r ## _HASH: \
702
+ return rb_tainted_str_new2(c::getHashName().c_str());
703
+ # include "defs/hashes.def"
704
+
705
+ # define HMAC_ALGORITHM_X(klass, r, c, s) \
706
+ case r ## _HMAC: \
707
+ return rb_tainted_str_new2(c::getHashName().c_str());
708
+ # include "defs/hmacs.def"
709
+ }
710
+ }
711
+
712
+
713
+ /**
714
+ * call-seq:
715
+ * algorithm_name => String
716
+ *
717
+ * Returns the name of the algorithm being used.
718
+ */
719
+ VALUE rb_digest_algorithm_name(VALUE self)
720
+ {
721
+ JHash *hash = NULL;
722
+ Data_Get_Struct(self, JHash, hash);
723
+ return rb_module_digest_name(self, INT2NUM(hash->getHashType()));
724
+ }
725
+
726
+
727
+ /**
728
+ * Clears a Digest's plaintext and hashtext.
729
+ */
730
+ VALUE rb_digest_clear(VALUE self)
731
+ {
732
+ JHash *hash = NULL;
733
+ Data_Get_Struct(self, JHash, hash);
734
+ hash->clear();
735
+ return Qnil;
736
+ }
737
+
738
+
739
+ /**
740
+ * call-seq:
741
+ * validate => Boolean
742
+ *
743
+ * Validates if the digest text is a valid digest for plaintext.
744
+ */
745
+ VALUE rb_digest_validate(VALUE self)
746
+ {
747
+ JHash *hash = NULL;
748
+ Data_Get_Struct(self, JHash, hash);
749
+ if (hash->validate()) {
750
+ return Qtrue;
751
+ }
752
+ else {
753
+ return Qfalse;
754
+ }
755
+ }
756
+
757
+
758
+ /* Instance version of <tt>CryptoPP#digest_io</tt>. */
759
+ static string digest_digest_io(VALUE self, VALUE io, bool hex)
760
+ {
761
+ try {
762
+ JHash *hash;
763
+ Data_Get_Struct(self, JHash, hash);
764
+ return hash->hashRubyIO(&io, hex);
765
+ }
766
+ catch (Exception& e) {
767
+ rb_raise(rb_eCryptoPP_Error, e.GetWhat().c_str());
768
+ }
769
+ }
770
+
771
+ /**
772
+ * call-seq:
773
+ * digest_io(in) => String
774
+ *
775
+ * Instance version of <tt>CryptoPP#digest_io</tt>.
776
+ */
777
+ VALUE rb_digest_digest_io(VALUE self, VALUE io)
778
+ {
779
+ string retval = digest_digest_io(self, io, false);
780
+ return rb_tainted_str_new(retval.data(), retval.length());
781
+ }
782
+
783
+ /**
784
+ * call-seq:
785
+ * digest_io_hex(in) => String
786
+ *
787
+ * Instance version of <tt>CryptoPP#digest_io_hex</tt>.
788
+ */
789
+ VALUE rb_digest_digest_io_hex(VALUE self, VALUE io)
790
+ {
791
+ string retval = digest_digest_io(self, io, true);
792
+ return rb_tainted_str_new(retval.data(), retval.length());
793
+ }
794
+
795
+
796
+ /**
797
+ * call-seq:
798
+ * digest_list => Array
799
+ *
800
+ * Returns an Array of available Digest algorithms.
801
+ */
802
+ VALUE rb_module_digest_list(VALUE self)
803
+ {
804
+ VALUE ary;
805
+ ary = rb_ary_new();
806
+
807
+ # define CHECKSUM_ALGORITHM_X(klass, r, c, s) \
808
+ rb_ary_push(ary, INT2NUM(r ##_CHECKSUM));
809
+ # include "defs/checksums.def"
810
+
811
+ # define HASH_ALGORITHM_X(klass, r, c, s) \
812
+ rb_ary_push(ary, INT2NUM(r ##_HASH));
813
+ # include "defs/hashes.def"
814
+
815
+ return ary;
816
+ }
817
+
818
+
819
+ /* Figure out options for a HMAC. */
820
+ static void digest_hmac_options(VALUE self, VALUE options)
821
+ {
822
+ digest_options(self, options);
823
+
824
+ {
825
+ VALUE key = rb_hash_aref(options, ID2SYM(rb_intern("key")));
826
+ VALUE key_hex = rb_hash_aref(options, ID2SYM(rb_intern("key_hex")));
827
+ if (!NIL_P(key) && !NIL_P(key_hex)) {
828
+ rb_raise(rb_eCryptoPP_Error, "can't set both key and key_hex in options");
829
+ }
830
+ else if (!NIL_P(key)) {
831
+ digest_hmac_key_eq(self, key, false);
832
+ }
833
+ else if (!NIL_P(key_hex)) {
834
+ digest_hmac_key_eq(self, key_hex, true);
835
+ }
836
+ }
837
+
838
+ {
839
+ VALUE key_length = rb_hash_aref(options, ID2SYM(rb_intern("key_length")));
840
+ if (!NIL_P(key_length)) {
841
+ rb_digest_hmac_key_length_eq(self, key_length);
842
+ }
843
+ }
844
+ }
845
+
846
+
847
+ /**
848
+ * call-seq:
849
+ * hmac_factory(algorithm) => CryptoPP::HMAC
850
+ * hmac_factory(algorithm, plaintext, key) => CryptoPP::HMAC
851
+ * hmac_factory(algorithm, options) => CryptoPP::HMAC
852
+ *
853
+ * Creates a new HMAC object.
854
+ */
855
+ VALUE rb_module_hmac_factory(int argc, VALUE *argv, VALUE self)
856
+ {
857
+ if (argc < 1 || argc > 3) {
858
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 1-3)", argc);
859
+ }
860
+ else {
861
+ JHash* hash = NULL;
862
+ VALUE algorithm = argv[0];
863
+ VALUE retval;
864
+
865
+ if (!IS_HMAC(digest_sym_to_const(algorithm))) {
866
+ rb_raise(rb_eCryptoPP_Error, "invalid HMAC algorithm");
867
+ }
868
+ else {
869
+ try {
870
+ hash = digest_factory(algorithm);
871
+ retval = wrap_digest_in_ruby(hash);
872
+ }
873
+ catch (Exception& e) {
874
+ if (hash != NULL) {
875
+ delete hash;
876
+ }
877
+ rb_raise(rb_eCryptoPP_Error, e.GetWhat().c_str());
878
+ }
879
+ if (argc >= 2) {
880
+ if (TYPE(argv[1]) == T_STRING) {
881
+ digest_plaintext_eq(retval, argv[1], false);
882
+ if (argc == 3) {
883
+ Check_Type(argv[2], T_STRING);
884
+ digest_hmac_key_eq(retval, argv[2], false);
885
+ }
886
+ hash->hash();
887
+ }
888
+ else if (argc > 2) {
889
+ rb_raise(rb_eArgError, "wrong argument types (expected a String or a Hash");
890
+ }
891
+ else {
892
+ digest_hmac_options(retval, argv[1]);
893
+ }
894
+ }
895
+ return retval;
896
+ }
897
+ }
898
+ }
899
+
900
+ #define HMAC_ALGORITHM_X(klass, r, n, s) \
901
+ VALUE rb_digest_hmac_ ## r ##_new(int argc, VALUE *argv, VALUE self) \
902
+ { \
903
+ if (argc > 2) { \
904
+ rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc); \
905
+ } \
906
+ else { \
907
+ VALUE retval; \
908
+ JHash* hash = NULL; \
909
+ try { \
910
+ hash = digest_factory(ID2SYM(rb_intern(# s))); \
911
+ retval = wrap_digest_in_ruby(hash); \
912
+ } \
913
+ catch (Exception& e) { \
914
+ if (hash != NULL) { \
915
+ delete hash; \
916
+ } \
917
+ rb_raise(rb_eCryptoPP_Error, e.GetWhat().c_str()); \
918
+ } \
919
+ if (argc >= 1) { \
920
+ if (TYPE(argv[0]) == T_STRING) { \
921
+ digest_plaintext_eq(retval, argv[0], false); \
922
+ if (argc == 2) { \
923
+ Check_Type(argv[1], T_STRING); \
924
+ digest_hmac_key_eq(retval, argv[1], false); \
925
+ } \
926
+ hash->hash(); \
927
+ } \
928
+ else if (argc > 1) { \
929
+ rb_raise(rb_eArgError, "wrong argument types (expected a String or a Hash"); \
930
+ } \
931
+ else { \
932
+ digest_hmac_options(retval, argv[0]); \
933
+ } \
934
+ } \
935
+ return retval; \
936
+ } \
937
+ }
938
+ #include "defs/hmacs.def"
939
+
940
+
941
+ /* Set the key. The true length of the key might not be what you expect,
942
+ * as different algorithms behave differently */
943
+ static string digest_hmac_key_eq(VALUE self, VALUE key, bool hex)
944
+ {
945
+ JHash *hash = NULL;
946
+ Check_Type(key, T_STRING);
947
+ Data_Get_Struct(self, JHash, hash);
948
+ ((JHMAC*) hash)->setKey(string(StringValuePtr(key), RSTRING(key)->len), hex);
949
+ return ((JHMAC*) hash)->getKey(hex);
950
+ }
951
+
952
+ /**
953
+ * call-seq:
954
+ * key=(key)
955
+ *
956
+ * Sets the key on a HMAC in binary.
957
+ */
958
+ VALUE rb_digest_hmac_key_eq(VALUE self, VALUE key)
959
+ {
960
+ digest_hmac_key_eq(self, key, false);
961
+ return key;
962
+ }
963
+
964
+ /**
965
+ * call-seq:
966
+ * key_hex=(key)
967
+ *
968
+ * Sets the key on a HMAC in hex.
969
+ */
970
+ VALUE rb_digest_hmac_key_hex_eq(VALUE self, VALUE key)
971
+ {
972
+ digest_hmac_key_eq(self, key, true);
973
+ return key;
974
+ }
975
+
976
+
977
+ /* Get the key. */
978
+ static string digest_hmac_key(VALUE self, bool hex)
979
+ {
980
+ JHash *hash = NULL;
981
+ Data_Get_Struct(self, JHash, hash);
982
+ return ((JHMAC*) hash)->getKey(hex);
983
+ }
984
+
985
+ /**
986
+ * call-seq:
987
+ * key => String
988
+ *
989
+ * Returns the key from the HMAC in binary.
990
+ */
991
+ VALUE rb_digest_hmac_key(VALUE self)
992
+ {
993
+ string retval = digest_hmac_key(self, false);
994
+ return rb_tainted_str_new(retval.data(), retval.length());
995
+ }
996
+
997
+ /**
998
+ * call-seq:
999
+ * key_hex => String
1000
+ *
1001
+ * Returns the key from the HMAC in hex.
1002
+ */
1003
+ VALUE rb_digest_hmac_key_hex(VALUE self)
1004
+ {
1005
+ string retval = digest_hmac_key(self, false);
1006
+ return rb_tainted_str_new(retval.data(), retval.length());
1007
+ }
1008
+
1009
+
1010
+ /**
1011
+ * call-seq:
1012
+ * key_length=(length)
1013
+ *
1014
+ * Sets the key length. Some HMACs require rather specific key lengths,
1015
+ * and if the key length you attempt to set is invalid, an exception will
1016
+ * be thrown. The key length being set is set in terms of bytes in binary, not
1017
+ * hex characters.
1018
+ */
1019
+ VALUE rb_digest_hmac_key_length_eq(VALUE self, VALUE l)
1020
+ {
1021
+ JHash *hash = NULL;
1022
+ unsigned int length = NUM2UINT(l);
1023
+ Data_Get_Struct(self, JHash, hash);
1024
+ ((JHMAC*) hash)->setKeylength(length);
1025
+ if (((JHMAC*) hash)->getKeylength() != length) {
1026
+ rb_raise(rb_eCryptoPP_Error, "tried to set a key length of %d but %d was used", length, ((JHMAC*) hash)->getKeylength());
1027
+ }
1028
+ else {
1029
+ return l;
1030
+ }
1031
+ }
1032
+
1033
+
1034
+ /**
1035
+ * call-seq:
1036
+ * key_length=(length) => Integer
1037
+ *
1038
+ * Sets the key length. Some HMACs require rather specific key lengths,
1039
+ * and if the key length you attempt to set is invalid, an exception will
1040
+ * be thrown. The key length being set is set in terms of bytes in binary, not
1041
+ * hex characters.
1042
+ */
1043
+ VALUE rb_digest_hmac_key_length(VALUE self)
1044
+ {
1045
+ JHash *hash = NULL;
1046
+ Data_Get_Struct(self, JHash, hash);
1047
+ return rb_fix_new(((JHMAC*) hash)->getKeylength());
1048
+ }
1049
+
1050
+
1051
+ /* Digest the plaintext. */
1052
+ static string module_hmac_digest(int argc, VALUE *argv, VALUE self, bool hex)
1053
+ {
1054
+ JHash *hash;
1055
+ VALUE algorithm, plaintext, key;
1056
+
1057
+ rb_scan_args(argc, argv, "12", &algorithm, &plaintext, &key);
1058
+ Check_Type(plaintext, T_STRING);
1059
+ {
1060
+ string retval;
1061
+ hash = digest_factory(algorithm);
1062
+ hash->setPlaintext(string(StringValuePtr(plaintext), RSTRING(plaintext)->len));
1063
+ if (argc == 3) {
1064
+ Check_Type(plaintext, T_STRING);
1065
+ ((JHMAC*) hash)->setKey(string(StringValuePtr(key), RSTRING(key)->len));
1066
+ }
1067
+ hash->hash();
1068
+ retval = hash->getHashtext(hex);
1069
+
1070
+ delete hash;
1071
+ return retval;
1072
+ }
1073
+ }
1074
+
1075
+ /**
1076
+ * call-seq:
1077
+ * digest(algorithm, plaintext) => String
1078
+ * digest(algorithm, plaintext, key) => String
1079
+ *
1080
+ * Singleton method for digesting with a HMAC. The plaintext and key values
1081
+ * are in binary and the return value is in binary.
1082
+ */
1083
+ VALUE rb_module_hmac_digest(int argc, VALUE *argv, VALUE self)
1084
+ {
1085
+ string retval = module_hmac_digest(argc, argv, self, false);
1086
+ return rb_tainted_str_new(retval.data(), retval.length());
1087
+ }
1088
+
1089
+ /**
1090
+ * call-seq:
1091
+ * digest_hex(algorithm, plaintext) => String
1092
+ * digest_hex(algorithm, plaintext, key) => String
1093
+ *
1094
+ * Singleton method for digesting with a HMAC. The plaintext and key values
1095
+ * are in binary and the return value is in hex.
1096
+ */
1097
+ VALUE rb_module_hmac_digest_hex(int argc, VALUE *argv, VALUE self)
1098
+ {
1099
+ string retval = module_hmac_digest(argc, argv, self, true);
1100
+ return rb_tainted_str_new(retval.data(), retval.length());
1101
+ }
1102
+
1103
+
1104
+ /**
1105
+ * call-seq:
1106
+ * hmac_list => Array
1107
+ *
1108
+ * Returns an Array of available HMAC algorithms.
1109
+ */
1110
+ VALUE rb_module_hmac_list(VALUE self)
1111
+ {
1112
+ VALUE ary;
1113
+ ary = rb_ary_new();
1114
+
1115
+ # define HMAC_ALGORITHM_X(klass, r, c, s) \
1116
+ rb_ary_push(ary, ID2SYM(rb_intern(# s)));
1117
+ # include "defs/hmacs.def"
1118
+
1119
+ return ary;
1120
+ }