cryptopp 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }