├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── kotlinc.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── LICENSE ├── README.md ├── luna-sample.iml ├── luna-sample.paw ├── manifest.yml ├── mvnw ├── mvnw.cmd ├── pom.xml └── src └── main └── java └── io └── pivotal └── luna ├── Application.java ├── CryptoController.java ├── KeyPairController.java ├── SecurityProvidersController.java └── Util.java /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .idea/libraries 3 | .idea/tasks.xml 4 | .idea/workspace.xml 5 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | luna-sample -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 33 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThalesGroup/java-buildpack-luna-sample/c7f1080e987ee276e10ac863b0c789d5cb7fb6be/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2017 - Gemalto 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A REST-ful sample application that exercises the Luna HSM. 2 | 3 | To do this, it exposes four cryptography REST endpoints that expect to recieve a JSON payload. Each endpoint returns values that can be used as arguments to the other endpoints. 4 | 5 | * `POST /encrypt` - `message`, a message to encrypt. 6 | * `POST /decrypt` - `cipher-text`, a base64 encoded encrypted message to decrypt. 7 | * `POST /sign` - `message`, a message to sign. 8 | * `POST /verify` - `message` and `signature`, a signature to verify against a message. 9 | 10 | In addition to these, two information endpoints are exposed. 11 | 12 | * `GET /key-pair` - Returns the base64 encoded private and public keys. 13 | * `GET /security-providers` - Lists all of the installed Java security providers. 14 | -------------------------------------------------------------------------------- /luna-sample.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | file://$MODULE_DIR$/src/main/java/io/pivotal/luna/Application.java 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /luna-sample.paw: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 134481920 7 | 507C9772-92C6-445C-96A3-AA07F6AF8D2B 8 | 129 9 | 10 | 11 | 12 | NSPersistenceFrameworkVersion 13 | 640 14 | NSStoreModelVersionHashes 15 | 16 | LMCookieJar 17 | 18 | Fttmf2L4PrGvKUF496+nqgVVGek45TjOe7sUMtjNg8I= 19 | 20 | LMEnvironment 21 | 22 | uzBoVFcO4YvR9/3ej4AJ1UOOsA/u5DKY2aemusoIseU= 23 | 24 | LMEnvironmentDomain 25 | 26 | yM1GPGHdquS8IWLtuczlNoqKhIhD9FW6IReSfFffJgs= 27 | 28 | LMEnvironmentVariable 29 | 30 | P8e0lYd5JZKRabS/eXVSOJ4oitilz67xtv+pLqW1Jqg= 31 | 32 | LMEnvironmentVariableValue 33 | 34 | my5hNPJ51oDCSa8EgdNxWAnRcDLcERUGjtuXnzhSxQ0= 35 | 36 | LMKeyValue 37 | 38 | bIXXbyYF2xAv2MXg8JTVFsslmMKuvsfnR86QdUcFkdM= 39 | 40 | LMRequest 41 | 42 | kYB6By9dZHqmH3YNw3h9tYPoxeG5ZWHPfhLXXp7OLFs= 43 | 44 | LMRequestGroup 45 | 46 | N3ml+gYVWc4m0LSGLnBDJ37p9isOc41y+TtaM0Eacrc= 47 | 48 | LMRequestTreeItem 49 | 50 | ak+hYb/lDeG55U0kgGvU5ej7HUltUj0RTrX5z/izNrs= 51 | 52 | 53 | NSStoreModelVersionHashesVersion 54 | 3 55 | NSStoreModelVersionIdentifiers 56 | 57 | LMDocumentVersion3 58 | 59 | 60 | 61 | 62 | 63 | 64 | 8159870D-E564-4996-A921-7B9E2EDADFFD 65 | 3 66 | Cryptography 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 5B840FB0-9F62-4B92-8BB5-8FBFA6A3D045 75 | ["http:\\/\\/",{"data":{"environmentVariable":"DA54FC74-63E9-48BB-AAA5-CDDEEC746ACA"},"identifier":"com.luckymarmot.EnvironmentVariableDynamicValue"},"\\/encrypt"] 76 | 1 77 | 1 78 | 0 79 | 0 80 | POST 81 | 0 82 | [{"data":{"json":"{\\"message\\":\\"Sample Message\\"}"},"identifier":"com.luckymarmot.JSONDynamicValue"}] 83 | 0 84 | Encrypt 85 | 86 | 87 | 88 | 89 | 90 | application/json 91 | 0 92 | Content-Type 93 | 1 94 | 95 | 96 | 97 | 98 | 99 | 100 | 0 101 | 1 102 | 103 | 104 | 105 | 106 | 107 | 108 | application/json 109 | Content-Type 110 | 0 111 | 1 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 0 120 | 121 | 1 122 | 123 | 124 | 125 | 126 | 127 | 128 | 1ECBBB98-5D5C-40A4-95F8-FA98525B6823 129 | ["http:\\/\\/",{"data":{"environmentVariable":"DA54FC74-63E9-48BB-AAA5-CDDEEC746ACA"},"identifier":"com.luckymarmot.EnvironmentVariableDynamicValue"},"\\/decrypt"] 130 | 1 131 | 1 132 | 0 133 | 0 134 | POST 135 | 0 136 | [{"data":{"json":"{\\"cipher-text\\":\\"[{\\\\\\"data\\\\\\":{\\\\\\"request\\\\\\":\\\\\\"5B840FB0-9F62-4B92-8BB5-8FBFA6A3D045\\\\\\",\\\\\\"keyPath\\\\\\":[\\\\\\"cipher-text\\\\\\"],\\\\\\"format\\\\\\":0},\\\\\\"identifier\\\\\\":\\\\\\"com.luckymarmot.ResponseBodyPathDynamicValue\\\\\\"}]\\"}"},"identifier":"com.luckymarmot.JSONDynamicValue"}] 137 | 1 138 | Decrypt 139 | 140 | 141 | 142 | 143 | 144 | BDC8555E-82BC-42B7-8A66-6C33378B4F48 145 | ["http:\\/\\/",{"data":{"environmentVariable":"DA54FC74-63E9-48BB-AAA5-CDDEEC746ACA"},"identifier":"com.luckymarmot.EnvironmentVariableDynamicValue"},"\\/key-pair"] 146 | 1 147 | 1 148 | 0 149 | 0 150 | GET 151 | 0 152 | 1 153 | Key Pair 154 | 155 | 156 | 157 | 158 | 159 | application/json 160 | 0 161 | Content-Type 162 | 1 163 | 164 | 165 | 166 | 167 | 168 | 169 | 1E620466-41CF-49F8-B947-445655F93609 170 | 0 171 | Default Domain 172 | 173 | 174 | 175 | 176 | DA54FC74-63E9-48BB-AAA5-CDDEEC746ACA 177 | 0 178 | host 179 | 180 | 181 | 182 | 183 | C19FBA45-64D6-4E62-8A3F-B1B0C4C11116 184 | ["http:\\/\\/",{"data":{"environmentVariable":"DA54FC74-63E9-48BB-AAA5-CDDEEC746ACA"},"identifier":"com.luckymarmot.EnvironmentVariableDynamicValue"},"\\/sign"] 185 | 1 186 | 1 187 | 0 188 | 0 189 | POST 190 | 0 191 | [{"data":{"json":"{\\"message\\":\\"Sample Message\\"}"},"identifier":"com.luckymarmot.JSONDynamicValue"}] 192 | 2 193 | Sign 194 | 195 | 196 | 197 | 198 | 199 | application/json 200 | 0 201 | Content-Type 202 | 1 203 | 204 | 205 | 206 | 207 | 208 | 209 | ADB9DE6F-3943-4C3D-AC25-1368CFA293D9 210 | 1 211 | Default Jar 212 | 213 | 214 | AF71BA8A-0111-4C59-B0E1-8B9AD7C6EE37 215 | ["http:\\/\\/",{"data":{"environmentVariable":"DA54FC74-63E9-48BB-AAA5-CDDEEC746ACA"},"identifier":"com.luckymarmot.EnvironmentVariableDynamicValue"},"\\/verify"] 216 | 1 217 | 1 218 | 0 219 | 0 220 | POST 221 | 0 222 | [{"data":{"json":"{\\"message\\":\\"[{\\\\\\"data\\\\\\":{\\\\\\"request\\\\\\":\\\\\\"C19FBA45-64D6-4E62-8A3F-B1B0C4C11116\\\\\\",\\\\\\"keyPath\\\\\\":[\\\\\\"message\\\\\\"],\\\\\\"format\\\\\\":0},\\\\\\"identifier\\\\\\":\\\\\\"com.luckymarmot.ResponseBodyPathDynamicValue\\\\\\"}]\\",\\"signature\\":\\"[{\\\\\\"data\\\\\\":{\\\\\\"request\\\\\\":\\\\\\"C19FBA45-64D6-4E62-8A3F-B1B0C4C11116\\\\\\",\\\\\\"keyPath\\\\\\":[\\\\\\"signature\\\\\\"],\\\\\\"format\\\\\\":0},\\\\\\"identifier\\\\\\":\\\\\\"com.luckymarmot.ResponseBodyPathDynamicValue\\\\\\"}]\\"}"},"identifier":"com.luckymarmot.JSONDynamicValue"}] 223 | 3 224 | Verify 225 | 226 | 227 | 228 | 229 | 230 | 08CEC372-8981-4619-A772-EA2FD1F052AE 231 | ["http:\\/\\/",{"data":{"environmentVariable":"DA54FC74-63E9-48BB-AAA5-CDDEEC746ACA"},"identifier":"com.luckymarmot.EnvironmentVariableDynamicValue"},"\\/security-providers"] 232 | 1 233 | 1 234 | 0 235 | 0 236 | GET 237 | 0 238 | 2 239 | Security Providers 240 | 241 | 242 | 243 | 244 | 245 | 667ADF70-4449-4004-A168-EF92B787C53D 246 | 0 247 | PWS 248 | 249 | 250 | 251 | 252 | luna-sample.cfapps.io 253 | 254 | 255 | 256 | 257 | 258 | 1 259 | 260 | 1 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 1 269 | 270 | 1 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 1 279 | 280 | 1 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 2 289 | 290 | 1 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 1 299 | 300 | 1 301 | 302 | 303 | 304 | 305 | 306 | -------------------------------------------------------------------------------- /manifest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | applications: 3 | - name: luna-sample 4 | memory: 1G 5 | instances: 1 6 | path: target/luna-sample-1-SNAPSHOT.jar 7 | buildpack: https://github.com/cloudfoundry/java-buildpack.git 8 | services: 9 | - myhsm 10 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 4.0.0 9 | 10 | 11 | org.springframework.boot 12 | spring-boot-starter-parent 13 | 1.5.3.RELEASE 14 | 15 | 16 | io.pivotal 17 | luna-sample 18 | 1-SNAPSHOT 19 | jar 20 | 21 | 22 | 5.4.1-2 23 | 1.8 24 | 25 | 26 | 27 | 28 | com.safenet-inc 29 | luna-provider 30 | ${luna-provider.version} 31 | provided 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-actuator 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-web 40 | 41 | 42 | 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-maven-plugin 48 | 49 | 50 | 51 | 52 | 53 | 54 | secret-repository 55 | http://do-not-give-this-url-to-anyone.download.pivotal.io.s3.amazonaws.com/maven 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/main/java/io/pivotal/luna/Application.java: -------------------------------------------------------------------------------- 1 | package io.pivotal.luna; 2 | 3 | import com.safenetinc.luna.LunaSlotManager; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.DependsOn; 9 | 10 | import javax.crypto.Cipher; 11 | import java.security.GeneralSecurityException; 12 | import java.security.KeyPair; 13 | import java.security.KeyPairGenerator; 14 | import java.security.Signature; 15 | 16 | @SpringBootApplication 17 | public class Application { 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(Application.class, args); 21 | } 22 | 23 | @Bean 24 | Cipher decryptionCipher(KeyPair keyPair) throws GeneralSecurityException { 25 | Cipher cipher = Cipher.getInstance("RSA/NONE/NoPadding", "LunaProvider"); 26 | cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate()); 27 | return cipher; 28 | } 29 | 30 | @Bean 31 | Cipher encryptionCipher(KeyPair keyPair) throws GeneralSecurityException { 32 | Cipher cipher = Cipher.getInstance("RSA/NONE/NoPadding", "LunaProvider"); 33 | cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic()); 34 | return cipher; 35 | } 36 | 37 | @Bean 38 | @DependsOn("slotManager") 39 | KeyPair keyPair() throws GeneralSecurityException { 40 | KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", "LunaProvider"); 41 | keyPairGenerator.initialize(1024); 42 | return keyPairGenerator.generateKeyPair(); 43 | } 44 | 45 | @Bean 46 | Signature signingSignature(KeyPair keyPair) throws GeneralSecurityException { 47 | Signature signature = Signature.getInstance("RSA"); 48 | signature.initSign(keyPair.getPrivate()); 49 | return signature; 50 | } 51 | 52 | @Bean(destroyMethod = "logout") 53 | LunaSlotManager slotManager(@Value("${vcap.services.myhsm.credentials.crypto_service_id}") String tokenLabel, 54 | @Value("${vcap.services.myhsm.credentials.crypto_service_password}") String password) { 55 | LunaSlotManager slotManager = LunaSlotManager.getInstance(); 56 | slotManager.login(tokenLabel, password); 57 | return slotManager; 58 | } 59 | 60 | @Bean 61 | Signature verificationSignature(KeyPair keyPair) throws GeneralSecurityException { 62 | Signature signature = Signature.getInstance("RSA"); 63 | signature.initVerify(keyPair.getPublic()); 64 | return signature; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/io/pivotal/luna/CryptoController.java: -------------------------------------------------------------------------------- 1 | package io.pivotal.luna; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.beans.factory.annotation.Qualifier; 7 | import org.springframework.http.MediaType; 8 | import org.springframework.web.bind.annotation.RequestBody; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import javax.crypto.Cipher; 14 | import java.nio.charset.Charset; 15 | import java.security.GeneralSecurityException; 16 | import java.security.Signature; 17 | import java.util.Base64; 18 | import java.util.Map; 19 | import java.util.Optional; 20 | 21 | import static io.pivotal.luna.Util.zip; 22 | 23 | @RestController 24 | final class CryptoController { 25 | 26 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 27 | 28 | private final Base64.Decoder decoder = Base64.getDecoder(); 29 | 30 | private final Cipher decryptionCipher; 31 | 32 | private final Base64.Encoder encoder = Base64.getEncoder(); 33 | 34 | private final Cipher encryptionCipher; 35 | 36 | private final Signature signingSignature; 37 | 38 | private final Signature verificationSignature; 39 | 40 | @Autowired 41 | CryptoController(@Qualifier("decryptionCipher") Cipher decryptionCipher, 42 | @Qualifier("encryptionCipher") Cipher encryptionCipher, 43 | @Qualifier("signingSignature") Signature signingSignature, 44 | @Qualifier("verificationSignature") Signature verificationSignature) { 45 | this.decryptionCipher = decryptionCipher; 46 | this.encryptionCipher = encryptionCipher; 47 | this.signingSignature = signingSignature; 48 | this.verificationSignature = verificationSignature; 49 | } 50 | 51 | @RequestMapping(method = RequestMethod.POST, value = "/decrypt", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) 52 | Map decrypt(@RequestBody Map payload) throws GeneralSecurityException { 53 | String cipherText = Optional.of(payload.get("cipher-text")) 54 | .orElseThrow(() -> new IllegalArgumentException("Payload must contain 'cipher-text'")); 55 | 56 | this.logger.info("Decrypting Cipher Text '{}'", cipherText); 57 | 58 | this.decryptionCipher.update(this.decoder.decode(cipherText)); 59 | String message = new String(this.decryptionCipher.doFinal(), Charset.defaultCharset()).trim(); 60 | 61 | return zip(new String[]{"cipher-text", "message"}, new String[]{cipherText, message}); 62 | } 63 | 64 | @RequestMapping(method = RequestMethod.POST, value = "/encrypt", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) 65 | Map encrypt(@RequestBody Map payload) throws GeneralSecurityException { 66 | String message = Optional.of(payload.get("message")) 67 | .orElseThrow(() -> new IllegalArgumentException("Payload must contain 'message'")); 68 | 69 | this.logger.info("Encrypting Message '{}'", message); 70 | 71 | this.encryptionCipher.update(message.getBytes(Charset.defaultCharset())); 72 | String cipherText = this.encoder.encodeToString(this.encryptionCipher.doFinal()); 73 | 74 | return zip(new String[]{"message", "cipher-text"}, new String[]{message, cipherText}); 75 | } 76 | 77 | @RequestMapping(method = RequestMethod.POST, value = "/sign", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) 78 | Map sign(@RequestBody Map payload) throws GeneralSecurityException { 79 | String message = Optional.of(payload.get("message")) 80 | .orElseThrow(() -> new IllegalArgumentException("Payload must contain 'message'")); 81 | 82 | this.logger.info("Signing Message '{}'", message); 83 | 84 | this.signingSignature.update(message.getBytes(Charset.defaultCharset())); 85 | String signature = this.encoder.encodeToString(this.signingSignature.sign()); 86 | 87 | return zip(new String[]{"message", "signature"}, new String[]{message, signature}); 88 | } 89 | 90 | @RequestMapping(method = RequestMethod.POST, value = "/verify", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) 91 | Map verify(@RequestBody Map payload) throws GeneralSecurityException { 92 | String message = Optional.of(payload.get("message")) 93 | .orElseThrow(() -> new IllegalArgumentException("Payload must contain 'message'")); 94 | String signature = Optional.of(payload.get("signature")) 95 | .orElseThrow(() -> new IllegalArgumentException("Payload must contain 'signature'")); 96 | 97 | this.logger.info("Verifying Message '{}' and Signature '{}'", message, signature); 98 | 99 | this.verificationSignature.update(message.getBytes(Charset.defaultCharset())); 100 | boolean verified = this.verificationSignature.verify(this.decoder.decode(signature)); 101 | 102 | return zip(new String[]{"message", "signature", "verified"}, new Object[]{message, signature, verified}); 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/main/java/io/pivotal/luna/KeyPairController.java: -------------------------------------------------------------------------------- 1 | package io.pivotal.luna; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestMethod; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import java.security.KeyPair; 9 | import java.util.Base64; 10 | import java.util.Map; 11 | 12 | import static io.pivotal.luna.Util.zip; 13 | 14 | @RestController 15 | final class KeyPairController { 16 | 17 | private final KeyPair keyPair; 18 | 19 | @Autowired 20 | KeyPairController(KeyPair keyPair) { 21 | this.keyPair = keyPair; 22 | } 23 | 24 | @RequestMapping(method = RequestMethod.GET, value = "/key-pair") 25 | Map keyPair() { 26 | String privateKey = Base64.getEncoder().encodeToString(this.keyPair.getPrivate().getEncoded()); 27 | String publicKey = Base64.getEncoder().encodeToString(this.keyPair.getPublic().getEncoded()); 28 | 29 | return zip(new String[]{"private", "public"}, new String[]{privateKey, publicKey}); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/pivotal/luna/SecurityProvidersController.java: -------------------------------------------------------------------------------- 1 | package io.pivotal.luna; 2 | 3 | import org.springframework.web.bind.annotation.RequestMapping; 4 | import org.springframework.web.bind.annotation.RequestMethod; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import java.security.Provider; 8 | import java.security.Security; 9 | import java.util.Arrays; 10 | import java.util.List; 11 | import java.util.stream.Collectors; 12 | 13 | @RestController 14 | final class SecurityProvidersController { 15 | 16 | @RequestMapping(method = RequestMethod.GET, value = "/security-providers") 17 | List securityProviders() { 18 | return Arrays.stream(Security.getProviders()) 19 | .map(ProviderProjection::new) 20 | .collect(Collectors.toList()); 21 | } 22 | 23 | static final class ProviderProjection { 24 | 25 | private final Provider provider; 26 | 27 | private ProviderProjection(Provider provider) { 28 | this.provider = provider; 29 | } 30 | 31 | public String getInfo() { 32 | return this.provider.getInfo(); 33 | } 34 | 35 | public String getName() { 36 | return this.provider.getName(); 37 | } 38 | 39 | public double getVersion() { 40 | return this.provider.getVersion(); 41 | } 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/io/pivotal/luna/Util.java: -------------------------------------------------------------------------------- 1 | package io.pivotal.luna; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | final class Util { 7 | 8 | private Util() { 9 | } 10 | 11 | static Map zip(K[] keys, V[] values) { 12 | Map map = new HashMap<>(); 13 | for (int i = 0; i < keys.length; i++) { 14 | map.put(keys[i], values[i]); 15 | } 16 | return map; 17 | } 18 | } 19 | --------------------------------------------------------------------------------