├── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src ├── main └── java │ └── jsse │ ├── AES.java │ ├── BlockCipher.java │ ├── SSEUtil.java │ ├── SWP.java │ ├── SearchableCipher.java │ ├── StreamCipher.java │ └── WDDS.java └── test └── java └── jsse ├── AESTest.java ├── SWPTest.java ├── StreamCipherTest.java └── WDDSTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | .idea 4 | jsse.iml 5 | target 6 | 7 | # Mobile Tools for Java (J2ME) 8 | .mtj.tmp/ 9 | 10 | # Package Files # 11 | *.jar 12 | *.war 13 | *.ear 14 | 15 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 16 | hs_err_pid* 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | (This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.) 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | {description} 474 | Copyright (C) {year} {fullname} 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 489 | USA 490 | 491 | Also add information on how to contact you by electronic and paper mail. 492 | 493 | You should also get your employer (if you work as a programmer) or your 494 | school, if any, to sign a "copyright disclaimer" for the library, if 495 | necessary. Here is a sample; alter the names: 496 | 497 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 498 | library `Frob' (a library for tweaking knobs) written by James Random 499 | Hacker. 500 | 501 | {signature of Ty Coon}, 1 April 1990 502 | Ty Coon, President of Vice 503 | 504 | That's all there is to it! 505 | 506 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | jsse is Symmetric Searchable Encryption Library in Java 3 | 4 | jsse is developed by Sashank Dara (krishna.sashank@gmail.com) 5 | 6 | Currently it has implementation of techniques published in 7 | 8 | Citation : 9 | [1] SWP scheme : Song, Dawn Xiaoding, David Wagner, and Adrian Perrig. "Practical techniques for searches on encrypted data." 10 | Security and Privacy, 2000. S&P 2000. Proceedings. 2000 IEEE Symposium on. IEEE, 2000. 11 | [2] WDDS scheme : SWaters, Brent R., et al. "Building an Encrypted and Searchable Audit Log." NDSS. Vol. 4. 2004. 12 | 13 | This is a personal *research prototype* use it at your own risk. 14 | 15 | Internally uses AES from BouncyCastle Library 16 | Also uses FNR for space efficiency so make sure you install [libfnr] (https://github.com/cisco/libfnr) and [jfnr] (https://github.com/cisco/jfnr) 17 | 18 | If you want to refer this library 19 | LICENSE -- LGPL (2.1) license copy under which this library is being released 20 | 21 | RUN : Import the source code in any editor like IntelliJ or Eclipse 22 | Junit test cases provided contains usage and demo applications 23 | 24 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | jsse 5 | jsse 6 | jar 7 | 1.0-SNAPSHOT 8 | jsse 9 | http://maven.apache.org 10 | 11 | 12 | 13 | org.apache.maven.plugins 14 | maven-compiler-plugin 15 | 3.1 16 | 17 | 1.8 18 | 1.8 19 | 20 | 21 | 22 | 23 | 24 | 25 | junit 26 | junit 27 | 3.8.1 28 | test 29 | 30 | 31 | org.bouncycastle 32 | bcprov-jdk15on 33 | 1.51 34 | 35 | 36 | cisco.com.jfnr 37 | jfnr 38 | 1.0-SNAPSHOT 39 | system 40 | ${project.basedir}/../jfnr/target/jfnr-1.0-SNAPSHOT-jar-with-dependencies.jar 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/main/java/jsse/AES.java: -------------------------------------------------------------------------------- 1 | package jsse; 2 | 3 | /* 4 | * 5 | * jsse is Symmetric Searchable Encryption Library in Java 6 | * 7 | * jsse is developed by Sashank Dara (sashank.dara@gmail.com) 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | **/ 24 | 25 | import javax.crypto.Cipher; 26 | import javax.crypto.spec.IvParameterSpec; 27 | import javax.crypto.spec.SecretKeySpec; 28 | import java.nio.ByteBuffer; 29 | import java.security.InvalidParameterException; 30 | 31 | 32 | public class AES implements BlockCipher { 33 | 34 | protected Cipher cipher; 35 | protected SecretKeySpec keySpec ; 36 | byte[] ivBytes = null; 37 | 38 | public AES(String mode, SecretKeySpec spec) throws InvalidParameterException { 39 | try { 40 | keySpec = spec ; 41 | cipher = Cipher.getInstance(mode, "BC"); 42 | } catch (Exception e){ 43 | throw new InvalidParameterException("Invalid Parameters" + e.getMessage()); 44 | } 45 | 46 | } 47 | public AES(String mode, SecretKeySpec spec, byte[] ivBytes) throws InvalidParameterException{ 48 | try { 49 | keySpec = spec ; 50 | this.ivBytes = ivBytes; 51 | cipher = Cipher.getInstance(mode, "BC"); 52 | } catch (Exception e){ 53 | throw new InvalidParameterException("Invalid Parameters" + e.getMessage()); 54 | } 55 | } 56 | public AES(String mode, byte[] key) throws InvalidParameterException { 57 | byte[] fullKey = new byte[16]; 58 | 59 | if(key == null ) 60 | throw new InvalidParameterException("Key is empty cannot proceed" ); 61 | if(key.length > 16) 62 | throw new InvalidParameterException("Key Size > 16 bytes" + key.length); 63 | 64 | System.arraycopy(key,0,fullKey,0,key.length); 65 | if(key.length < 16){ 66 | for (int i = key.length ; i < 16 ; i ++) 67 | fullKey[i] = 0 ; 68 | } 69 | 70 | try { 71 | keySpec = new SecretKeySpec(fullKey, "AES"); 72 | cipher = Cipher.getInstance(mode, "BC"); 73 | } catch (Exception e){ 74 | throw new InvalidParameterException("Invalid Parameters" + e.getMessage()); 75 | } 76 | 77 | } 78 | 79 | public byte[] encrypt(byte[] plainBytes) throws Exception { 80 | 81 | cipher.init(Cipher.ENCRYPT_MODE, keySpec); 82 | return cipher.doFinal(plainBytes); 83 | } 84 | 85 | 86 | public byte[] decrypt(byte[] cipherText) throws Exception { 87 | 88 | cipher.init(Cipher.DECRYPT_MODE, keySpec); 89 | return cipher.doFinal(cipherText); 90 | } 91 | 92 | public byte[] getIvBytes(long id){ 93 | byte[] idBytes = ByteBuffer.allocate(16).putLong(id).array(); 94 | return SSEUtil.xorTwoByteArrays(ivBytes, idBytes); 95 | } 96 | 97 | public byte[] encrypt(byte[] plainBytes, byte[] ivBytes) throws Exception { 98 | 99 | cipher.init(Cipher.ENCRYPT_MODE, keySpec,new IvParameterSpec(ivBytes) ); 100 | 101 | return cipher.doFinal(plainBytes); 102 | } 103 | 104 | public byte[] decrypt(byte[] cipherBytes, byte[] ivBytes) throws Exception { 105 | 106 | cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ivBytes)); 107 | 108 | return cipher.doFinal(cipherBytes); 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/jsse/BlockCipher.java: -------------------------------------------------------------------------------- 1 | package jsse; 2 | 3 | /* 4 | * 5 | * jsse is Symmetric Searchable Encryption Library in Java 6 | * 7 | * jsse is developed by Sashank Dara (sashank.dara@gmail.com) 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | **/ 24 | public interface BlockCipher { 25 | 26 | public byte[] encrypt(byte[] plainBytes) throws Exception; 27 | public byte[] decrypt(byte[] cipherText) throws Exception; 28 | public byte[] encrypt(byte[] plainBytes, byte[] ivBytes) throws Exception; 29 | 30 | 31 | public byte[] decrypt(byte[] cipherText, byte[] ivBytes) throws Exception; 32 | 33 | public byte[] getIvBytes(long id); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/jsse/SSEUtil.java: -------------------------------------------------------------------------------- 1 | package jsse; 2 | /* 3 | * 4 | * jsse is Symmetric Searchable Encryption Library in Java 5 | * 6 | * jsse is developed by Sashank Dara (sashank.dara@gmail.com) 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | * 22 | **/ 23 | 24 | import javax.crypto.SecretKey; 25 | import javax.crypto.SecretKeyFactory; 26 | import javax.crypto.spec.PBEKeySpec; 27 | import javax.crypto.spec.SecretKeySpec; 28 | import java.security.NoSuchAlgorithmException; 29 | import java.security.SecureRandom; 30 | import java.security.spec.InvalidKeySpecException; 31 | 32 | 33 | public class SSEUtil { 34 | 35 | 36 | public static byte[] xorTwoByteArrays(byte[] byteArray1, byte[] byteArray2) { 37 | int maxLength = byteArray1.length > byteArray2.length ? byteArray1.length : byteArray2.length; 38 | int minLength = byteArray1.length > byteArray2.length ? byteArray2.length : byteArray1.length; 39 | 40 | byte[] xorBytes = new byte[maxLength]; 41 | for (int i = 0; i < minLength ; i++){ 42 | xorBytes[i] = (byte) (byteArray1[i] ^ byteArray2[i]); 43 | } 44 | if (maxLength == byteArray1.length) 45 | System.arraycopy(byteArray1,minLength,xorBytes,minLength,maxLength-minLength); 46 | if (maxLength == byteArray2.length) 47 | System.arraycopy(byteArray2,minLength,xorBytes,minLength,maxLength-minLength); 48 | 49 | return xorBytes; 50 | } 51 | 52 | public static byte[] getRandomBytes(int count) { 53 | 54 | // Generate the Salt 55 | SecureRandom random = new SecureRandom(); 56 | byte[] saltyBytes = new byte[count]; 57 | random.nextBytes(saltyBytes); 58 | 59 | return saltyBytes; 60 | } 61 | public static SecretKeySpec getSecretKeySpec(String password, byte[] saltyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException { 62 | int pswdIterations = 65536; 63 | int keySize = 128; 64 | 65 | // Derive the key 66 | SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 67 | PBEKeySpec spec = new PBEKeySpec( password.toCharArray(),saltyBytes, 68 | pswdIterations, keySize ); 69 | 70 | 71 | SecretKey secretKey = factory.generateSecret(spec); 72 | 73 | return new SecretKeySpec(secretKey.getEncoded(), "AES"); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/jsse/SWP.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * jsse is Symmetric Searchable Encryption Library in Java 4 | * 5 | * jsse is developed by Sashank Dara (sashank.dara@gmail.com) 6 | * 7 | * SWP is a popular searchable symmetric encryption technique 8 | * developed by Song, Wagner and Perrig 9 | * 10 | * Reference: Song, Dawn Xiaoding, David Wagner, and Adrian Perrig. "Practical techniques for searches on encrypted data." 11 | * Security and Privacy, 2000. S&P 2000. Proceedings. 2000 IEEE Symposium on. IEEE, 2000. 12 | * 13 | * This library is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Lesser General Public 15 | * License as published by the Free Software Foundation; either 16 | * version 2.1 of the License, or (at your option) any later version. 17 | * 18 | * This library is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | * Lesser General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU Lesser General Public 24 | * License along with this library; if not, write to the Free Software 25 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 26 | * 27 | **/ 28 | 29 | package jsse; 30 | 31 | import com.cisco.fnr.FNR; 32 | 33 | import javax.crypto.spec.SecretKeySpec; 34 | import java.security.InvalidParameterException; 35 | import java.util.Arrays; 36 | 37 | 38 | public class SWP implements SearchableCipher { 39 | 40 | private AES aesCipher, aesTmpCipher = null; 41 | private FNR fnrCipher, fnrTmpCipher = null; 42 | private String type; 43 | public static int BLOCK_SIZE; 44 | public static int BLOCK_BYTES; 45 | private byte[] seedBytes; 46 | 47 | 48 | private final int left; 49 | private final int right ; 50 | 51 | public SWP(SecretKeySpec spec, String type, double loadFactor, int blockSize) throws InvalidParameterException{ 52 | 53 | if( loadFactor <= 0 || loadFactor > 1) 54 | throw new InvalidParameterException("Invalid Load Factor"); 55 | 56 | StreamCipher.init(spec); 57 | seedBytes = SSEUtil.getRandomBytes(16); // For Nonce 58 | switch (type){ 59 | case "AES" : 60 | if(blockSize != 128) 61 | throw new InvalidParameterException("Invalid Block Size for AES"); 62 | aesCipher = new AES("AES/ECB/PKCS7Padding", spec); 63 | break; 64 | case "FNR" : 65 | fnrCipher = new FNR(spec.getEncoded(),"tweak",blockSize); 66 | break; 67 | default: 68 | throw new InvalidParameterException("Invalid Block Cipher type"); 69 | } 70 | 71 | // init parameters 72 | this.type = type ; 73 | BLOCK_SIZE = blockSize; 74 | BLOCK_BYTES = BLOCK_SIZE/Byte.SIZE; 75 | this.left = ((int) (loadFactor * BLOCK_BYTES)); 76 | this.right = BLOCK_BYTES - left ; 77 | } 78 | 79 | public byte[] encrypt(byte[] plainBytes, long recordID) throws Exception { 80 | 81 | if (plainBytes == null) 82 | return new byte[0]; 83 | 84 | /* Generate Stream Cipher Bytes */ 85 | byte[] streamCipherBytes = StreamCipher.getRandomStreamOfBytes( 86 | recordID, seedBytes); 87 | 88 | byte[] blockCipherBytes = encrypt(plainBytes); 89 | 90 | /* Split the cipher Bytes into {left, Right} */ 91 | byte[] blockCipherBytesLeft = Arrays.copyOfRange(blockCipherBytes, 0, 92 | left); 93 | byte[] streamCipherBytesLeft = Arrays.copyOfRange(streamCipherBytes, 0, 94 | left); 95 | 96 | /* Generate search layer */ 97 | byte[] tmpBytes = getSearchLayer(blockCipherBytesLeft,streamCipherBytesLeft); 98 | 99 | byte[] searchLayerBytesRight; 100 | if(right == 0) // No false positives but additional storage 101 | searchLayerBytesRight = Arrays.copyOfRange(tmpBytes, 0, BLOCK_BYTES); 102 | else //Expect false positives while searching 103 | searchLayerBytesRight = Arrays.copyOfRange(tmpBytes,0,right); 104 | 105 | 106 | byte[] searchLayerBytes = new byte[streamCipherBytesLeft.length+ searchLayerBytesRight.length]; 107 | 108 | System.arraycopy(streamCipherBytesLeft, 0, searchLayerBytes, 0, left); 109 | System.arraycopy(searchLayerBytesRight, 0, searchLayerBytes, left, 110 | searchLayerBytesRight.length); 111 | 112 | return SSEUtil.xorTwoByteArrays(blockCipherBytes, searchLayerBytes); 113 | } 114 | 115 | public byte[] decrypt(byte[] cipherBytes, long recordID) throws Exception { 116 | if (cipherBytes == null) 117 | return new byte[0]; 118 | 119 | /* Generate a Stream Cipher */ 120 | byte[] streamCipherBytes = 121 | StreamCipher.getRandomStreamOfBytes(recordID, seedBytes); 122 | 123 | byte[] streamCipherBytesLeft = 124 | Arrays.copyOfRange(streamCipherBytes, 0, left); 125 | 126 | 127 | /* Split the cipher Bytes into {left, Right} */ 128 | byte[] cipherBytesLeft = Arrays.copyOfRange(cipherBytes, 0, left); 129 | byte[] cipherBytesRight = Arrays.copyOfRange(cipherBytes, left, cipherBytes.length); 130 | 131 | /* 132 | * Peel off the left bytes of search layer from cipherText to get left 133 | * bytes of Block Cipher 134 | */ 135 | 136 | byte[] blockCipherBytesLeft = SSEUtil.xorTwoByteArrays(cipherBytesLeft, 137 | streamCipherBytesLeft); 138 | 139 | if(blockCipherBytesLeft.length == BLOCK_BYTES) 140 | return decrypt(blockCipherBytesLeft); 141 | 142 | else { 143 | 144 | /* 145 | * compute the right bytes of search layer 146 | * */ 147 | 148 | byte[] tmpBytes = getSearchLayer(blockCipherBytesLeft,streamCipherBytesLeft); 149 | byte[] tmpBytesRight = Arrays.copyOfRange(tmpBytes, 0, right); 150 | 151 | 152 | byte[] blockCipherBytesRight = SSEUtil.xorTwoByteArrays( 153 | cipherBytesRight, tmpBytesRight); 154 | 155 | byte[] blockLayerBytes = new byte[BLOCK_BYTES]; 156 | System.arraycopy(blockCipherBytesLeft, 0, blockLayerBytes, 0, left); 157 | System.arraycopy(blockCipherBytesRight, 0, blockLayerBytes, left, right); 158 | 159 | return decrypt(blockLayerBytes); 160 | } 161 | } 162 | 163 | public byte[] getTrapDoor(byte[] plainBytes) throws Exception { 164 | return encrypt(plainBytes); 165 | } 166 | 167 | /* 168 | * Blind folded Match ! 169 | */ 170 | 171 | public boolean isMatch(byte[] trapDoorBytes, byte[] cipherBytes) 172 | throws Exception { 173 | 174 | if(cipherBytes == null || trapDoorBytes == null) 175 | return false; 176 | 177 | /* Peel off the search layer bytes of given layer */ 178 | byte[] searchBytes = SSEUtil.xorTwoByteArrays(trapDoorBytes, cipherBytes); 179 | byte[] searchBytesLeft = Arrays.copyOfRange(searchBytes, 0, left); 180 | byte[] searchBytesRight = Arrays.copyOfRange(searchBytes,left,cipherBytes.length); 181 | 182 | 183 | /* Split the trapDoorBytes into {left, Right} of Left bytes and Right bytes */ 184 | byte[] trapDoorBytesLeft = Arrays.copyOfRange(trapDoorBytes,0,left); 185 | 186 | /* Verify search layer */ 187 | byte[] tmpBytes = getSearchLayer(trapDoorBytesLeft, searchBytesLeft); 188 | byte[] tmpBytesRight ; 189 | if(right == 0) 190 | tmpBytesRight = Arrays.copyOfRange(tmpBytes,0,BLOCK_BYTES); 191 | else 192 | tmpBytesRight = Arrays.copyOfRange(tmpBytes,0,right); 193 | 194 | return Arrays.equals(searchBytesRight,tmpBytesRight) ; 195 | 196 | } 197 | 198 | public byte[] encrypt(byte[] plainBytes) throws Exception { 199 | switch (type){ 200 | case "AES" : 201 | return aesCipher.encrypt(plainBytes); 202 | case "FNR" : 203 | return fnrCipher.encrypt(plainBytes); 204 | } 205 | return null; 206 | } 207 | 208 | public byte[] decrypt(byte[] cipherBytes) throws Exception { 209 | switch (type){ 210 | case "AES" : 211 | return aesCipher.decrypt(cipherBytes); 212 | case "FNR" : 213 | return fnrCipher.decrypt(cipherBytes); 214 | } 215 | return null; 216 | } 217 | 218 | private byte[] getSearchLayer(byte[] key, byte[] data) throws Exception { 219 | switch (type) { 220 | case "AES" : 221 | if(aesTmpCipher == null) 222 | aesTmpCipher = new AES("AES/ECB/PKCS7Padding", key); 223 | return aesTmpCipher.encrypt(data); 224 | case "FNR" : 225 | if(fnrTmpCipher == null) 226 | fnrTmpCipher = new FNR(key,"tweak",data.length * Byte.SIZE); //Not Block Size 227 | return fnrTmpCipher.encrypt(data); 228 | } 229 | return null; 230 | } 231 | 232 | } 233 | 234 | -------------------------------------------------------------------------------- /src/main/java/jsse/SearchableCipher.java: -------------------------------------------------------------------------------- 1 | package jsse; 2 | /* 3 | * 4 | * jsse is Symmetric Searchable Encryption Library in Java 5 | * 6 | * jsse is developed by Sashank Dara (sashank.dara@gmail.com) 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | * 22 | **/ 23 | 24 | public interface SearchableCipher { 25 | 26 | byte[] encrypt(byte[] plainBytes) throws Exception; 27 | 28 | byte[] decrypt(byte[] cipherBytes)throws Exception; 29 | 30 | byte[] getTrapDoor(byte[] plainBytes) throws Exception; 31 | 32 | public boolean isMatch(byte[] trapDoorBytes, byte[] cipherBytes)throws Exception; 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/jsse/StreamCipher.java: -------------------------------------------------------------------------------- 1 | package jsse; 2 | /* 3 | * 4 | * jsse is Symmetric Searchable Encryption Library in Java 5 | * 6 | * jsse is developed by Sashank Dara (sashank.dara@gmail.com) 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2.1 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 | * 22 | **/ 23 | 24 | import javax.crypto.Cipher; 25 | import javax.crypto.spec.IvParameterSpec; 26 | import javax.crypto.spec.SecretKeySpec; 27 | import java.nio.ByteBuffer; 28 | 29 | 30 | public class StreamCipher { 31 | private static StreamCipher ourInstance = new StreamCipher(); 32 | protected static Cipher cipher = null; 33 | protected static SecretKeySpec keySpec ; 34 | public static StreamCipher getInstance() { 35 | return ourInstance; 36 | } 37 | 38 | private StreamCipher(){ 39 | 40 | } 41 | public static boolean init(SecretKeySpec spec){ 42 | try { 43 | 44 | keySpec = spec; 45 | cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC"); 46 | 47 | return true; 48 | } 49 | catch (Exception e){ 50 | // Do Some thing later . 51 | } 52 | return false; 53 | } 54 | 55 | 56 | public static byte[] getRandomStreamOfBytes(long recordId, byte[] seedBytes) throws Exception { 57 | try { 58 | byte[] nonce = getNonce(recordId, seedBytes); 59 | cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(nonce)); 60 | } 61 | catch (Exception e){ 62 | // do something later ; 63 | } 64 | 65 | // Plain text is 0 always we don't really care 66 | return cipher.doFinal(ByteBuffer.allocate(16).putInt(0).array()); 67 | } 68 | private static byte[] getNonce(long recordId, byte[] seedBytes){ 69 | byte[] nonce = new byte[16]; 70 | 71 | try { 72 | 73 | byte[] recordIdBytes = ByteBuffer.allocate(16).putLong(recordId).array(); 74 | nonce = SSEUtil.xorTwoByteArrays(seedBytes, recordIdBytes); 75 | 76 | } catch (Exception e) { 77 | e.printStackTrace(); 78 | } 79 | return nonce; 80 | } 81 | public byte[] encrypt(byte[] plainBytes) throws Exception { 82 | 83 | cipher.init(Cipher.ENCRYPT_MODE, keySpec); 84 | return cipher.doFinal(plainBytes); 85 | } 86 | 87 | 88 | public byte[] decrypt(byte[] cipherText) throws Exception { 89 | 90 | cipher.init(Cipher.DECRYPT_MODE, keySpec); 91 | return cipher.doFinal(cipherText); 92 | } 93 | 94 | public byte[] encrypt(byte[] plainBytes, byte[] ivBytes) throws Exception { 95 | 96 | cipher.init(Cipher.ENCRYPT_MODE, keySpec,new IvParameterSpec(ivBytes) ); 97 | 98 | return cipher.doFinal(plainBytes); 99 | } 100 | 101 | public byte[] decrypt(byte[] cipherBytes, byte[] ivBytes) throws Exception { 102 | 103 | cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ivBytes)); 104 | 105 | return cipher.doFinal(cipherBytes); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/jsse/WDDS.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * jsse is Symmetric Searchable Encryption Library in Java 4 | * 5 | * jsse is developed by Sashank Dara (sashank.dara@gmail.com) 6 | * 7 | * WBDD is a searchable symmetric encryption technique 8 | * developed by Brent R Waters and Dirk Balfanz, and Glenn Durfee,and Diana K Smetters 9 | * 10 | * Reference: SWaters, Brent R., et al. "Building an Encrypted and Searchable Audit Log." NDSS. Vol. 4. 2004. 11 | * 12 | * This library is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU Lesser General Public 14 | * License as published by the Free Software Foundation; either 15 | * version 2.1 of the License, or (at your option) any later version. 16 | * 17 | * This library is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | * Lesser General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU Lesser General Public 23 | * License along with this library; if not, write to the Free Software 24 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 25 | * 26 | **/ 27 | 28 | package jsse; 29 | 30 | import com.cisco.fnr.FNR; 31 | 32 | import javax.crypto.spec.SecretKeySpec; 33 | import java.security.InvalidParameterException; 34 | import java.util.Arrays; 35 | 36 | 37 | public class WDDS implements SearchableCipher { 38 | 39 | private AES aesCipher, aesRndCipher = null; 40 | private FNR fnrCipher, fnrRndCipher = null; 41 | private String type; 42 | public static int BLOCK_SIZE; 43 | public static int BLOCK_BYTES; 44 | public static final String FLAG = "CAPTURE-THE-FLAG" ; //Ensure it is 16 letters i.e 16 bytes 45 | public static final String SMALL_FLAG = "FLAG" ; //Ensure it is 16 letters i.e 16 bytes 46 | private byte[] randomBytes; 47 | 48 | public WDDS(SecretKeySpec spec,String type, int blockSize,byte[] randBytes) throws InvalidParameterException{ 49 | 50 | switch (type){ 51 | case "AES" : 52 | if(blockSize != 128) 53 | throw new InvalidParameterException("Invalid Block Size for AES"); 54 | aesCipher = new AES("AES/ECB/PKCS7Padding", spec); 55 | 56 | break; 57 | case "FNR" : 58 | fnrCipher = new FNR(spec.getEncoded(),"tweak",blockSize); 59 | break; 60 | default: 61 | throw new InvalidParameterException("Invalid Block Cipher type"); 62 | } 63 | 64 | // init parameters 65 | this.type = type ; 66 | BLOCK_SIZE = blockSize; 67 | BLOCK_BYTES = BLOCK_SIZE/Byte.SIZE; 68 | randomBytes = randBytes; 69 | } 70 | 71 | 72 | public byte[] getTrapDoor(byte[] plainBytes) throws Exception { 73 | if (plainBytes == null) 74 | return new byte[0]; 75 | 76 | byte[] bBytes = getBBytes(plainBytes); 77 | 78 | return SSEUtil.xorTwoByteArrays(bBytes, FLAG.getBytes()); 79 | } 80 | 81 | public byte[] getBBytes(byte[] plainBytes) throws Exception { 82 | byte[] aBytes = encrypt(plainBytes); 83 | aesRndCipher = new AES("AES/ECB/NoPadding", aBytes); // Note: a_bytes is the key 84 | return aesRndCipher.encrypt(randomBytes); 85 | } 86 | 87 | /* 88 | * Blind folded Match ! 89 | */ 90 | 91 | public boolean isMatch(byte[] trapDoorBytes, byte[] bBytes) 92 | throws Exception { 93 | 94 | if(bBytes == null || trapDoorBytes == null) 95 | return false; 96 | 97 | byte[] flagBytes = SSEUtil.xorTwoByteArrays(trapDoorBytes,bBytes); 98 | 99 | return Arrays.equals(flagBytes, FLAG.getBytes()) ; 100 | 101 | } 102 | 103 | public byte[] encrypt(byte[] plainBytes) throws Exception { 104 | switch (type){ 105 | case "AES" : 106 | return aesCipher.encrypt(plainBytes); 107 | case "FNR" : 108 | return fnrCipher.encrypt(plainBytes); 109 | } 110 | return null; 111 | } 112 | 113 | public byte[] decrypt(byte[] cipherBytes) throws Exception { 114 | switch (type){ 115 | case "AES" : 116 | return aesCipher.decrypt(cipherBytes); 117 | case "FNR" : 118 | return fnrCipher.decrypt(cipherBytes); 119 | } 120 | return null; 121 | } 122 | 123 | } 124 | 125 | -------------------------------------------------------------------------------- /src/test/java/jsse/AESTest.java: -------------------------------------------------------------------------------- 1 | package jsse; 2 | 3 | /* 4 | * 5 | * jsse is Symmetric Searchable Encryption Library in Java 6 | * 7 | * jsse is developed by Sashank Dara (sashank.dara@gmail.com) 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | **/ 24 | 25 | import junit.framework.TestCase; 26 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 27 | import org.bouncycastle.util.encoders.Base64; 28 | 29 | import javax.crypto.spec.SecretKeySpec; 30 | import java.security.NoSuchAlgorithmException; 31 | import java.security.SecureRandom; 32 | import java.security.Security; 33 | import java.security.spec.InvalidKeySpecException; 34 | import java.util.Arrays; 35 | 36 | public class AESTest extends TestCase { 37 | 38 | SecretKeySpec keySpec; 39 | 40 | public void setUp() throws Exception { 41 | super.setUp(); 42 | String password = "test"; // NOT FOR PRODUCTION 43 | Security.addProvider(new BouncyCastleProvider()); 44 | 45 | keySpec = null; 46 | try { 47 | keySpec = SSEUtil.getSecretKeySpec(password, SSEUtil.getRandomBytes(16)); 48 | } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | 53 | public void tearDown() throws Exception { 54 | super.tearDown(); 55 | } 56 | 57 | public void testDeterministic() throws Exception { 58 | try { 59 | System.out.println("Test Deterministic"); 60 | 61 | BlockCipher blockCipher = new AES("AES/ECB/PKCS7Padding", keySpec); 62 | 63 | byte[] plainBytes = "Hello".getBytes(); 64 | byte[] cipherText = blockCipher.encrypt(plainBytes); 65 | byte[] plainText = blockCipher.decrypt(cipherText); 66 | 67 | if (Arrays.equals(plainBytes, plainText)) 68 | assertTrue("Deterministic Encryption Works" , true); 69 | else 70 | assertTrue("Deterministic Encryption Fails", false); 71 | } 72 | catch (Exception e){ 73 | assertTrue("Deterministic Encryption Does not Work" + e.getMessage() , false); 74 | } 75 | 76 | } 77 | 78 | public void testRandomized() throws Exception { 79 | try { 80 | System.out.println("Test Randomized"); 81 | SecureRandom random = new SecureRandom(); 82 | byte[] ivBytes = new byte[16]; 83 | random.nextBytes(ivBytes); 84 | 85 | AES randCipher = new AES("AES/CBC/PKCS7Padding", keySpec,ivBytes); 86 | 87 | byte[] plainBytes = Base64.encode("10.20.30.40".getBytes()); 88 | // byte[] idBytes = ByteBuffer.allocate(16).putLong(1).array(); 89 | // ivBytes = SSEUtil.xorTwoByteArrays(ivBytes, idBytes); 90 | 91 | byte[] idIvBytes = randCipher.getIvBytes(1L); 92 | byte[] cipherBytes = randCipher.encrypt(plainBytes, idIvBytes); 93 | byte[] decryptBytes = randCipher.decrypt(cipherBytes, idIvBytes); 94 | 95 | if (Arrays.equals(plainBytes, decryptBytes)) 96 | assertTrue("Randomized Encryption Works" , true); 97 | else 98 | assertTrue("Randomized Encryption Fails", false); 99 | } 100 | catch (Exception e){ 101 | assertTrue("Randomized Encryption Does not Work" + e.getMessage() , false); 102 | } 103 | 104 | } 105 | public void testBoundaries() throws Exception{ 106 | try { 107 | System.out.println("Test Boundaries"); 108 | 109 | BlockCipher blockCipher = new AES("AES/ECB/NoPadding", keySpec); 110 | 111 | byte[] plainBytes = "CAPTURE-THE-FLAG".getBytes(); 112 | byte[] cipherBytes = blockCipher.encrypt(plainBytes); 113 | byte[] plainText = blockCipher.decrypt(cipherBytes); 114 | 115 | if (Arrays.equals(plainBytes, plainText)) 116 | assertTrue("Deterministic Encryption Works" , true); 117 | else 118 | assertTrue("Deterministic Encryption Fails", false); 119 | 120 | if(cipherBytes.length == 16 ) 121 | assertTrue("Boundary Check Works" , true); 122 | else 123 | assertTrue("Boundary Check Fails" , false); 124 | 125 | blockCipher = new AES("AES/ECB/PKCS7Padding", keySpec); 126 | 127 | plainBytes = "CAPTURE-THE-FLAG".getBytes(); 128 | cipherBytes = blockCipher.encrypt(plainBytes); 129 | 130 | if(cipherBytes.length == 32 ) 131 | assertTrue("Boundary Check Works" , true); 132 | else 133 | assertTrue("Boundary Check Fails" , false); 134 | 135 | byte[] tmpCipherBytes; 136 | plainBytes = "CAPTURE-THE-FLAG1".getBytes(); 137 | tmpCipherBytes = blockCipher.encrypt(plainBytes); 138 | 139 | 140 | if(Arrays.equals(Arrays.copyOfRange(cipherBytes,0,16),Arrays.copyOfRange(tmpCipherBytes,0,16)) ) 141 | assertTrue("Cipher Prefix Matches" , true); 142 | else 143 | assertTrue("Cipher Prefix Does not Match" , false); 144 | 145 | 146 | /* 147 | blockCipher = new AES("AES/CBC/PKCS5Padding", keySpec); 148 | 149 | plainBytes = "CAPTURE-THE-FLAG".getBytes(); 150 | cipherBytes = blockCipher.encrypt(plainBytes,"0123456789012345".getBytes()); 151 | 152 | plainBytes = "CAPTURE-THE-FLAG1".getBytes(); 153 | tmpCipherBytes = blockCipher.encrypt(plainBytes, "0123456789012345".getBytes()); 154 | 155 | 156 | if(Arrays.equals(Arrays.copyOfRange(cipherBytes,0,16),Arrays.copyOfRange(tmpCipherBytes,0,16)) ) 157 | assertTrue("Cipher Prefix Matches" , true); 158 | else 159 | assertTrue("Cipher Prefix Does not Match" , false); 160 | 161 | */ 162 | 163 | plainBytes = "CAPTURE-THE-FLAG0123456789012345".getBytes(); 164 | cipherBytes = blockCipher.encrypt(plainBytes); 165 | plainText = blockCipher.decrypt(cipherBytes); 166 | 167 | if(cipherBytes.length == 48 ) 168 | assertTrue("Boundary Check Works" , true); 169 | else 170 | assertTrue("Boundary Check Fails" , false); 171 | 172 | 173 | } 174 | catch (Exception e){ 175 | assertTrue("Boundaries Does not Work" + e.getMessage() , false); 176 | } 177 | 178 | } 179 | } -------------------------------------------------------------------------------- /src/test/java/jsse/SWPTest.java: -------------------------------------------------------------------------------- 1 | package jsse; 2 | 3 | import com.cisco.fnr.FNRUtils; 4 | import junit.framework.Test; 5 | import junit.framework.TestCase; 6 | import junit.framework.TestSuite; 7 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 8 | 9 | import javax.crypto.spec.SecretKeySpec; 10 | import java.lang.reflect.Field; 11 | import java.security.Security; 12 | import java.util.Arrays; 13 | 14 | /* 15 | * 16 | * jsse is Symmetric Searchable Encryption Library in Java 17 | * 18 | * jsse is developed by Sashank Dara (sashank.dara@gmail.com) 19 | * 20 | * This library is free software; you can redistribute it and/or 21 | * modify it under the terms of the GNU Lesser General Public 22 | * License as published by the Free Software Foundation; either 23 | * version 2.1 of the License, or (at your option) any later version. 24 | * 25 | * This library is distributed in the hope that it will be useful, 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 28 | * Lesser General Public License for more details. 29 | * 30 | * You should have received a copy of the GNU Lesser General Public 31 | * License along with this library; if not, write to the Free Software 32 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 33 | * 34 | **/ 35 | 36 | public class SWPTest 37 | extends TestCase 38 | { 39 | private String password; 40 | 41 | /** 42 | * Create the test case 43 | * 44 | * @param testName name of the test case 45 | */ 46 | public SWPTest (String testName) 47 | 48 | { 49 | super( testName ); 50 | } 51 | 52 | /** 53 | * @return the suite of tests being tested 54 | */ 55 | public static Test suite() 56 | { 57 | return new TestSuite( SWPTest.class ); 58 | } 59 | 60 | public void setUp() throws Exception { 61 | super.setUp(); 62 | 63 | password = "test"; // NOT FOR PRODUCTION 64 | Security.addProvider(new BouncyCastleProvider()); 65 | } 66 | 67 | 68 | public void tearDown() throws Exception { 69 | super.tearDown(); 70 | } 71 | 72 | /** 73 | * Rigourous Test :-) 74 | * Searchable without False Positives 75 | * Notice that the load factor is 1 76 | */ 77 | public void testSWP_NO_FP_AES() { 78 | System.out.println("Test AES Searchable "); 79 | 80 | double loadFactor = 1; // No false positives but additional storage 81 | try { 82 | final SecretKeySpec secretKeySpec = SSEUtil.getSecretKeySpec(password, 83 | SSEUtil.getRandomBytes(20)); 84 | SWP swp = new SWP(secretKeySpec, "AES",loadFactor, 128); 85 | 86 | byte[] plainBytes = ("Hello").getBytes(); 87 | byte[] cipherText = swp.encrypt(plainBytes, 1); 88 | 89 | if(cipherText.length == 2 * SWP.BLOCK_BYTES) 90 | assertTrue("Additional Storage", true); 91 | else 92 | assertTrue("Strange",false); 93 | 94 | byte[] plainText = swp.decrypt(cipherText, 1); 95 | 96 | if (Arrays.equals(plainBytes, plainText)) 97 | assertTrue("Encryption and Decryption works !",true); 98 | else 99 | assertTrue("Failed", false); 100 | 101 | // Get Trapdoor 102 | byte[] trapDoor = swp.getTrapDoor(plainBytes); 103 | 104 | // Check Match 105 | if (swp.isMatch(trapDoor, cipherText)) 106 | assertTrue("Matching works Blind-foldedly !",true); 107 | else 108 | assertTrue("Matching Does not work !", false); 109 | 110 | 111 | } catch (Exception e){ 112 | e.printStackTrace(); 113 | assertTrue("Something went wrong .. some where !!! .." + e.getMessage(),false); 114 | } 115 | } 116 | public void testSWP_NO_FP_FNR() { 117 | System.out.println("Test FNR Searchable String "); 118 | 119 | double loadFactor = 1; // No false positives but additional storage 120 | try { 121 | String givenText = "192.168.1.1" ; 122 | 123 | byte[] plainBytes = FNRUtils.rankIPAddress(givenText); 124 | 125 | SWP swp = new SWP(SSEUtil.getSecretKeySpec(password, 126 | SSEUtil.getRandomBytes(20)), "FNR",loadFactor, plainBytes.length*Byte.SIZE); 127 | 128 | 129 | byte[] cipherBytes = swp.encrypt(plainBytes, 1); 130 | 131 | if(cipherBytes.length == 2 * SWP.BLOCK_BYTES) 132 | assertTrue("Additional Storage", true); 133 | else 134 | assertTrue("Strange",false); 135 | 136 | byte[] decryptBytes = swp.decrypt(cipherBytes, 1); 137 | 138 | 139 | if (Arrays.equals(plainBytes, decryptBytes)) 140 | assertTrue("Encryption and Decryption works !",true); 141 | else 142 | assertTrue("Failed", false); 143 | 144 | // Get Trapdoor 145 | byte[] trapDoor = swp.getTrapDoor(plainBytes); 146 | 147 | // Check Match 148 | if (swp.isMatch(trapDoor, cipherBytes)) 149 | assertTrue("Matching works Blind-foldedly !",true); 150 | else 151 | assertTrue("Matching Does not work !", false); 152 | 153 | 154 | } catch (Exception e){ 155 | e.printStackTrace(); 156 | assertTrue("Something went wrong .. some where !!! .." + e.getMessage(),false); 157 | } 158 | } 159 | public void testSWP_NO_FP_FNR_IP() { 160 | System.out.println("Test FNR Searchable IP Address "); 161 | 162 | double loadFactor = 1; // No false positives but additional storage 163 | try { 164 | String givenIp = "192.168.1.1" ; 165 | System.out.println("IPAddress " + givenIp); 166 | byte[] plainBytes = FNRUtils.rankIPAddress(givenIp); 167 | 168 | SWP swp = new SWP(SSEUtil.getSecretKeySpec(password, 169 | SSEUtil.getRandomBytes(20)), "FNR",loadFactor, plainBytes.length*Byte.SIZE); 170 | 171 | 172 | byte[] cipherBytes = swp.encrypt(plainBytes, 1); 173 | 174 | if(cipherBytes.length == 2 * SWP.BLOCK_BYTES) 175 | assertTrue("Additional Storage", true); 176 | else 177 | assertTrue("Strange",false); 178 | 179 | byte[] decryptBytes = swp.decrypt(cipherBytes, 1); 180 | 181 | 182 | if (Arrays.equals(plainBytes, decryptBytes)) 183 | assertTrue("Encryption and Decryption works !",true); 184 | else 185 | assertTrue("Failed", false); 186 | 187 | // Get Trapdoor 188 | byte[] trapDoor = swp.getTrapDoor(plainBytes); 189 | 190 | // Check Match 191 | if (swp.isMatch(trapDoor, cipherBytes)) 192 | assertTrue("Matching works Blind-foldedly !",true); 193 | else 194 | assertTrue("Matching Does not work !", false); 195 | 196 | 197 | } catch (Exception e){ 198 | e.printStackTrace(); 199 | assertTrue("Something went wrong .. some where !!! .." + e.getMessage(),false); 200 | } 201 | } 202 | 203 | /** 204 | * Rigourous Test :-) 205 | * SWP With no additional storage 206 | * Search could have False Positives 207 | * Notice that the load factor is < 1 208 | */ 209 | public void testSWP_NO_ADD_STORAGE_AES() { 210 | System.out.println("Test AES Searchable "); 211 | 212 | double loadFactor = 0.7; // No false positives but additional storage 213 | try { 214 | 215 | SWP swp = new SWP(SSEUtil.getSecretKeySpec(password, 216 | SSEUtil.getRandomBytes(20)), "AES",loadFactor, 128); 217 | 218 | byte[] plainBytes = ("Hello").getBytes(); 219 | byte[] cipherText = swp.encrypt(plainBytes, 1); 220 | 221 | if(cipherText.length != SWP.BLOCK_BYTES) 222 | assertTrue("Strange",false); 223 | else 224 | assertTrue("NO additional Storage", true); 225 | 226 | byte[] plainText = swp.decrypt(cipherText, 1); 227 | 228 | if (Arrays.equals(plainBytes, plainText)) 229 | assertTrue("Encryption and Decryption works !",true); 230 | else 231 | assertTrue("Failed", false); 232 | 233 | // Get Trapdoor 234 | byte[] trapDoor = swp.getTrapDoor(plainBytes); 235 | 236 | // Check Match 237 | if (swp.isMatch(trapDoor, cipherText)) 238 | assertTrue("Matching works Blind-foldedly !",true); 239 | else 240 | assertTrue("Matching Does not work !", false); 241 | 242 | 243 | } catch (Exception e){ 244 | e.printStackTrace(); 245 | assertTrue("Something went wrong .. some where !!! .." + e.getMessage(),false); 246 | } 247 | } 248 | 249 | public void testSWP_NO_ADD_STORAGE_FNR() { 250 | System.out.println("Test FNR Searchable String"); 251 | 252 | double loadFactor = 0.7; // No false positives but additional storage 253 | try { 254 | String givenText = "Hello" ; 255 | byte[] plainBytes = givenText.getBytes(); 256 | 257 | SWP swp = new SWP(SSEUtil.getSecretKeySpec(password, 258 | SSEUtil.getRandomBytes(20)), "FNR",loadFactor, plainBytes.length*Byte.SIZE); 259 | 260 | byte[] cipherText = swp.encrypt(plainBytes, 1); 261 | 262 | if(cipherText.length != SWP.BLOCK_BYTES) 263 | assertTrue("Strange",false); 264 | else 265 | assertTrue("No additional Storage", true); 266 | 267 | byte[] decryptBytes = swp.decrypt(cipherText, 1); 268 | 269 | if (Arrays.equals(plainBytes, decryptBytes)) 270 | assertTrue("Encryption and Decryption works !",true); 271 | else 272 | assertTrue("Failed", false); 273 | 274 | // Get Trapdoor 275 | byte[] trapDoor = swp.getTrapDoor(plainBytes); 276 | 277 | // Check Match 278 | if (swp.isMatch(trapDoor, cipherText)) 279 | assertTrue("Matching works Blind-foldedly !",true); 280 | else 281 | assertTrue("Matching Does not work !", false); 282 | 283 | 284 | } catch (Exception e){ 285 | e.printStackTrace(); 286 | assertTrue("Something went wrong .. some where !!! .." + e.getMessage(),false); 287 | } 288 | } 289 | public void testSWP_NO_ADD_STORAGE_FNR_IP() { 290 | System.out.println("Test FNR Searchable IPAddress"); 291 | 292 | double loadFactor = 0.7; // No false positives but additional storage 293 | try { 294 | String givenIp = "192.168.1.1" ; 295 | System.out.println("IPAddress " + givenIp); 296 | 297 | byte[] plainBytes = FNRUtils.rankIPAddress(givenIp); 298 | 299 | SWP swp = new SWP(SSEUtil.getSecretKeySpec(password, 300 | SSEUtil.getRandomBytes(20)), "FNR",loadFactor, plainBytes.length*Byte.SIZE); 301 | 302 | byte[] cipheBytes = swp.encrypt(plainBytes, 1); 303 | 304 | String cipherIp = FNRUtils.deRankIPAddress(cipheBytes); 305 | System.out.println("Cipher IPAddress " + cipherIp); 306 | 307 | if(cipheBytes.length != SWP.BLOCK_BYTES) 308 | assertTrue("Strange",false); 309 | else 310 | assertTrue("No additional Storage", true); 311 | 312 | byte[] decryptBytes = swp.decrypt(cipheBytes, 1); 313 | String decryptedIP = FNRUtils.deRankIPAddress(decryptBytes); 314 | System.out.println("Decrypted IPAddress " + decryptedIP); 315 | if (Arrays.equals(plainBytes, decryptBytes)) 316 | assertTrue("Encryption and Decryption works on bytes !",true); 317 | else 318 | assertTrue("Failed Encryption and Decryption works on bytes ", false); 319 | 320 | if(givenIp.equals(decryptedIP)) 321 | assertTrue("Encryption and Decryption works on IP Address !",true); 322 | else 323 | assertTrue("Failed Encryption and Decryption works on IP Address ", false); 324 | 325 | 326 | 327 | // Get Trapdoor 328 | byte[] trapDoor = swp.getTrapDoor(plainBytes); 329 | System.out.println("Trapdoor IPAddress " + FNRUtils.deRankIPAddress(trapDoor)); 330 | 331 | // Check Match 332 | if (swp.isMatch(trapDoor, cipheBytes)) 333 | assertTrue("Matching works Blind-foldedly !",true); 334 | else 335 | assertTrue("Matching Does not work !", false); 336 | 337 | 338 | } catch (Exception e){ 339 | e.printStackTrace(); 340 | assertTrue("Something went wrong .. some where !!! .." + e.getMessage(),false); 341 | } 342 | } 343 | 344 | public void testLoadFactor(){ 345 | System.out.println("Test Load factor "); 346 | double loadFactor= 0 ; 347 | 348 | try { 349 | new SWP(SSEUtil.getSecretKeySpec(password, 350 | SSEUtil.getRandomBytes(20)), "AES",loadFactor, 128); 351 | } catch (Exception e){ 352 | assertTrue(true); 353 | } 354 | 355 | loadFactor = 2; 356 | try { 357 | new SWP(SSEUtil.getSecretKeySpec(password, 358 | SSEUtil.getRandomBytes(20)), "AES",loadFactor, 128); 359 | } catch (Exception e){ 360 | assertTrue(true); 361 | } 362 | 363 | loadFactor = 1; 364 | try { 365 | new SWP(SSEUtil.getSecretKeySpec(password, 366 | SSEUtil.getRandomBytes(20)), "AES",loadFactor, 128); 367 | } catch (Exception e){ 368 | assertTrue(false); 369 | } 370 | 371 | loadFactor = 0.5; 372 | try { 373 | new SWP(SSEUtil.getSecretKeySpec(password, 374 | SSEUtil.getRandomBytes(20)), "AES",loadFactor, 128); 375 | } catch (Exception e){ 376 | assertTrue(false); 377 | } 378 | 379 | } 380 | } 381 | -------------------------------------------------------------------------------- /src/test/java/jsse/StreamCipherTest.java: -------------------------------------------------------------------------------- 1 | package jsse; 2 | 3 | /* 4 | * 5 | * jsse is Symmetric Searchable Encryption Library in Java 6 | * 7 | * jsse is developed by Sashank Dara (sashank.dara@gmail.com) 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 | * 23 | **/ 24 | 25 | import junit.framework.TestCase; 26 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 27 | 28 | import javax.crypto.spec.SecretKeySpec; 29 | import java.security.NoSuchAlgorithmException; 30 | import java.security.Security; 31 | import java.security.spec.InvalidKeySpecException; 32 | import java.util.Arrays; 33 | 34 | public class StreamCipherTest extends TestCase { 35 | 36 | public void setUp() throws Exception { 37 | super.setUp(); 38 | 39 | } 40 | 41 | public void tearDown() throws Exception { 42 | 43 | } 44 | 45 | public void testStream(){ 46 | Security.addProvider(new BouncyCastleProvider()); 47 | byte[] saltyBytes = SSEUtil.getRandomBytes(16); 48 | byte[] seedBytes = SSEUtil.getRandomBytes(16); 49 | SecretKeySpec spec; 50 | try { 51 | spec = SSEUtil.getSecretKeySpec("OPEN_SECRET_OPEN", saltyBytes); // not for production 52 | boolean init = StreamCipher.init(spec); 53 | if(!init) { 54 | System.out.print("Something went wrong quitting"); 55 | assertTrue(false); 56 | } 57 | } catch (NoSuchAlgorithmException | InvalidKeySpecException e ) { 58 | e.printStackTrace(); 59 | assertTrue(false); 60 | } 61 | 62 | 63 | byte[] randBytes1, randBytes2 ; 64 | try { 65 | randBytes1 = StreamCipher.getRandomStreamOfBytes(10, seedBytes); 66 | randBytes2 = StreamCipher.getRandomStreamOfBytes(10, seedBytes); 67 | 68 | // Test for equality 69 | 70 | if (Arrays.equals(randBytes1, randBytes2)) { 71 | System.out.println("Same"); 72 | assertTrue(true); 73 | } 74 | 75 | randBytes1 = StreamCipher.getRandomStreamOfBytes(10, seedBytes); 76 | randBytes2 = StreamCipher.getRandomStreamOfBytes(11, seedBytes); 77 | 78 | // Test for equality 79 | if (!Arrays.equals(randBytes1,randBytes2)) { 80 | System.out.println("Not Same"); 81 | assertTrue("Testing INEQUALITY",true); 82 | } 83 | 84 | } 85 | catch (Exception e){ 86 | System.out.println("Something went wrong .. some where .." + e.getMessage()); 87 | assertTrue(false); 88 | } 89 | 90 | 91 | } 92 | } -------------------------------------------------------------------------------- /src/test/java/jsse/WDDSTest.java: -------------------------------------------------------------------------------- 1 | package jsse; 2 | 3 | import junit.framework.TestCase; 4 | import org.bouncycastle.jce.provider.BouncyCastleProvider; 5 | 6 | import javax.crypto.spec.SecretKeySpec; 7 | import java.security.Security; 8 | import java.util.Arrays; 9 | import java.util.Base64; 10 | 11 | /** 12 | * Created by Sashank Dara on 06/10/15. 13 | */ 14 | public class WDDSTest extends TestCase { 15 | private String password; 16 | private SecretKeySpec secretKeySpec; 17 | private WDDS searchableCipher; 18 | private String plainText; 19 | 20 | public void setUp() throws Exception { 21 | super.setUp(); 22 | password = "test"; // NOT FOR PRODUCTION 23 | Security.addProvider(new BouncyCastleProvider()); 24 | secretKeySpec = SSEUtil.getSecretKeySpec(password, 25 | SSEUtil.getRandomBytes(20)); 26 | searchableCipher = new WDDS(secretKeySpec,"AES",128,SSEUtil.getRandomBytes(16)) ; 27 | } 28 | 29 | public void tearDown() throws Exception { 30 | super.tearDown(); 31 | } 32 | 33 | public void testCipher() throws Exception { 34 | plainText = "ไทย"; 35 | byte cipherBytes[] = searchableCipher.encrypt(plainText.getBytes()); 36 | byte plainBytes[] = searchableCipher.decrypt(cipherBytes); 37 | 38 | if(Arrays.equals(plainBytes, plainText.getBytes())) 39 | assertTrue("Encryption works",true); 40 | else 41 | assertFalse("Encryption Failed",false); 42 | 43 | } 44 | 45 | 46 | public void testBlindMatch() throws Exception { 47 | testCipher(); 48 | 49 | byte[] trapDoorBytes = searchableCipher.getTrapDoor(plainText.getBytes()); 50 | byte[] bBytes = searchableCipher.getBBytes(plainText.getBytes()); 51 | 52 | if(searchableCipher.isMatch(trapDoorBytes,bBytes)) 53 | assertTrue("Blind Match works",true); 54 | else 55 | assertFalse("Blind Match Failed",true); 56 | } 57 | 58 | 59 | } --------------------------------------------------------------------------------