├── .travis.yml ├── mvnvm.properties ├── test-common ├── src │ ├── main │ │ ├── resources │ │ │ ├── withpass │ │ │ │ ├── PASSPHRASE.txt │ │ │ │ ├── id_rsa.pub │ │ │ │ ├── id_dsa.pub │ │ │ │ ├── id_dsa │ │ │ │ ├── id_rsa │ │ │ │ ├── id_dsa.properties │ │ │ │ └── id_rsa.properties │ │ │ ├── b1024 │ │ │ │ ├── id_rsa.pub │ │ │ │ ├── id_dsa.pub │ │ │ │ ├── id_dsa │ │ │ │ ├── id_rsa │ │ │ │ ├── id_dsa.properties │ │ │ │ └── id_rsa.properties │ │ │ ├── b2048 │ │ │ │ ├── id_rsa.pub │ │ │ │ ├── id_rsa │ │ │ │ └── id_rsa.properties │ │ │ ├── b4096 │ │ │ │ ├── id_rsa.pub │ │ │ │ └── id_rsa │ │ │ └── authorized_keys │ │ └── java-templates │ │ │ └── net │ │ │ └── adamcin │ │ │ └── httpsig │ │ │ └── testutil │ │ │ └── package-info.java │ └── site │ │ └── site.xml └── pom.xml ├── .gitignore ├── hmac ├── README.md └── src │ ├── site │ └── site.xml │ ├── main │ ├── java-templates │ │ └── net │ │ │ └── adamcin │ │ │ └── httpsig │ │ │ └── hmac │ │ │ └── package-info.java │ └── java │ │ └── net │ │ └── adamcin │ │ └── httpsig │ │ └── hmac │ │ └── HmacKeyId.java │ └── test │ └── java │ └── net │ └── adamcin │ └── httpsig │ └── hmac │ └── HmacKeyTest.java ├── LICENSE ├── UNLICENSE ├── osgi └── src │ ├── main │ └── resources │ │ └── META-INF │ │ └── NOTICE.txt │ └── site │ └── site.xml ├── api └── src │ ├── site │ └── site.xml │ ├── main │ ├── java-templates │ │ └── net │ │ │ └── adamcin │ │ │ └── httpsig │ │ │ └── api │ │ │ └── package-info.java │ └── java │ │ └── net │ │ └── adamcin │ │ └── httpsig │ │ └── api │ │ ├── UserKey.java │ │ ├── KeyId.java │ │ ├── Algorithm.java │ │ ├── VerifyResult.java │ │ ├── Keychain.java │ │ ├── Key.java │ │ ├── Verifier.java │ │ └── Authorization.java │ └── test │ └── java │ └── net │ └── adamcin │ └── httpsig │ └── api │ ├── SignerTest.java │ ├── RequestContentTest.java │ ├── Base64Test.java │ ├── MockKey.java │ ├── MockKeychain.java │ ├── DefaultVerifierTest.java │ └── ConstantsTest.java ├── ssh-bc └── src │ ├── site │ └── site.xml │ ├── main │ ├── java-templates │ │ └── net │ │ │ └── adamcin │ │ │ └── httpsig │ │ │ └── ssh │ │ │ └── bc │ │ │ └── package-info.java │ └── java │ │ └── net │ │ └── adamcin │ │ └── httpsig │ │ └── ssh │ │ └── bc │ │ └── PEMUtil.java │ └── test │ └── java │ └── net │ └── adamcin │ └── httpsig │ └── ssh │ └── bc │ └── PEMUtilTest.java ├── ssh-jce └── src │ ├── site │ └── site.xml │ ├── main │ ├── java-templates │ │ └── net │ │ │ └── adamcin │ │ │ └── httpsig │ │ │ └── ssh │ │ │ └── jce │ │ │ └── package-info.java │ └── java │ │ └── net │ │ └── adamcin │ │ └── httpsig │ │ └── ssh │ │ └── jce │ │ ├── FingerprintableKey.java │ │ ├── UserFingerprintKeyId.java │ │ ├── UserKeysFingerprintKeyId.java │ │ ├── SSHRSASignature.java │ │ ├── SSHDSSSignature.java │ │ ├── FingerprintGenerator.java │ │ └── KeyFormat.java │ └── test │ └── java │ └── net │ └── adamcin │ └── httpsig │ └── ssh │ └── jce │ └── KeyFormatTest.java ├── ssh-jsch └── src │ ├── site │ └── site.xml │ ├── main │ └── java-templates │ │ └── net │ │ └── adamcin │ │ └── httpsig │ │ └── ssh │ │ └── jsch │ │ └── package-info.java │ └── test │ └── java │ └── net │ └── adamcin │ └── httpsig │ └── ssh │ └── jsch │ └── JschKeyTest.java ├── http-helpers └── src │ ├── site │ └── site.xml │ ├── main │ ├── java-templates │ │ └── net │ │ │ └── adamcin │ │ │ └── httpsig │ │ │ └── http │ │ │ ├── ning │ │ │ └── package-info.java │ │ │ ├── apache3 │ │ │ └── package-info.java │ │ │ ├── apache4 │ │ │ └── package-info.java │ │ │ └── servlet │ │ │ └── package-info.java │ └── java │ │ └── net │ │ └── adamcin │ │ └── httpsig │ │ └── http │ │ ├── apache3 │ │ ├── SignerCredentials.java │ │ ├── SignerCredentialsProvider.java │ │ ├── Http3Util.java │ │ └── Http3SignatureAuthScheme.java │ │ ├── apache4 │ │ ├── SignerCredentials.java │ │ ├── Http4Util.java │ │ └── Http4SignatureAuthScheme.java │ │ └── ning │ │ ├── AsyncSignatureCalculator.java │ │ └── RotateAndReplayResponseFilter.java │ └── test │ ├── resources │ └── logback.xml │ └── java │ └── net │ └── adamcin │ └── httpsig │ └── http │ ├── apache3 │ └── Http3UtilTest.java │ └── apache4 │ └── Http4UtilTest.java └── src └── site ├── xdoc └── index.xml └── site.xml /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java -------------------------------------------------------------------------------- /mvnvm.properties: -------------------------------------------------------------------------------- 1 | mvn_version=3.3.9 2 | -------------------------------------------------------------------------------- /test-common/src/main/resources/withpass/PASSPHRASE.txt: -------------------------------------------------------------------------------- 1 | dummydummy 2 | -------------------------------------------------------------------------------- /test-common/src/main/resources/b1024/id_rsa.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+Fz0pqK+XoCcukPhnPD+M1zb+FImbh5Lu3pkfW5DM67B6Hr9Q28LuWgNTfLqUn9o01W0TYzXDxtKG9psGuQ0wFJmqYJNbP6eRB3gimcr+C/eyy7N/evs8E36iMi7Si1piPd7QJ5l3D/tThI5cAACHYN0uqwphpXt4Lw2OZxIAQw== dummy@nowhere 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | *.log 3 | 4 | # sbt specific 5 | dist/* 6 | target/ 7 | lib_managed/ 8 | src_managed/ 9 | project/boot/ 10 | project/plugins/project/ 11 | 12 | # Scala-IDE specific 13 | .scala_dependencies 14 | 15 | # IntelliJ specific 16 | *.iml 17 | .idea/ 18 | lib/ 19 | 20 | */crx-quickstart/ -------------------------------------------------------------------------------- /test-common/src/main/resources/b2048/id_rsa.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/8kVdBX3dv6gtNl0YadNOcmoTsU+XQj9su9Q5EGiDNTQ9d7bqPW/Fckk4sa7QNB9lDls506iKdlSlh4AfFYrQaA3R0t+KLFtBw+ZGyhfUqin3RrIXotg9V1v/8leE/xy9tQNRLPT8YN0Qj0naguRmIp0del1gWwM4iyB5ZBA2ZITjOKNmzpDOL5UOs5TYNWP6ozMNbEdV515RvjiAlLz342O1dRGhT+0XUx5r2iq5D4CofGyl2BUTNzTJ/nLF5rETs6NTi8463HUC8JQ2a6d8HxO5LAh/1UBBvYR/38+LCnDpzDKl1j8FwAYpiRZuWMo+uMaI7ZjrJ6wDO4cicZ+R dummy@nowhere 2 | -------------------------------------------------------------------------------- /test-common/src/main/resources/withpass/id_rsa.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDwm2QdZogDqbOgG5KQgpQdDkb1iAIeH5Q3GOvr+LHtWWUxugdxk11yI28fO8WxAkg8gSTetJR9PQT0rvVIWZdjHpFhyLOiPpSz3+QkfPFilh7caPILfcLqivqmx4JMHXkMppn1u1n4ITbP/ZCaswX5S/zkEkGtBM/+3ckNlmxAEuaOJR1tXmdE9IiD6vPIIs9TeOYVkmpl17LTL82nKscOo1Wbof6MkuAeQutJJ6YFMWJSwx0kzAN5XSTrJvndArsCHayl4JTDNkkGj2wHMEh14MsMn+5/nbAN1xxpD4vfqG0k03dYFvk1EGhcWobBN6F/Pt7NWpZUaAdZ39wMTMH1 dummy@nowhere 2 | -------------------------------------------------------------------------------- /test-common/src/main/resources/b1024/id_dsa.pub: -------------------------------------------------------------------------------- 1 | ssh-dss AAAAB3NzaC1kc3MAAACBAJLg3Lqag97vrVWmS8gGIgCBI4qcu9PE5O5wc0ZdRniqaoUn/PUMCH4FD+0UJGlDeprZ8F2JWU4zuqqqUdGiCn138VvvD9MQ03Yl3oB8mDL5IXM819xOu850Kzm9x8MgwQmHVpgj5kg8n/YYYLsaolTHGGMeWGakEgNqmLMJDlCNAAAAFQC0bPtUr2TsNQaiLEQxIkrUIXUGBwAAAIAC6hGP8JKYKQde5a4SCbfJnoJWh1vqm4/+d0hhOSdtzE3xH8DBrm0EhLg8+pN6ldUdI0BaMhki4hX+8xqAOlPWQQP7iADEu7ZS29s3nZK8P9ztLv196ZM7AorufoYz8XfQaY4EPEMQHERSJ9tKmSS49uMb1J0rfrT2Nhc0J+98kQAAAIADJYhtXZF9HO0ZbB7uT6Xsdkoxwq1r0nfDSpXADYiqirVZvUXovmrMB30mnKKP49mi/Mp0yWmOKtE2twpZIrKk3JPNx8/SKc+WD0VknlItcetbJrB4FcpEhUh8wJSL2BdXF/zc7kao2U3xBk5SU7d4jy7X9DOA5ZM/5L5JA1RI+Q== dummy@nowhere 2 | -------------------------------------------------------------------------------- /test-common/src/main/resources/withpass/id_dsa.pub: -------------------------------------------------------------------------------- 1 | ssh-dss AAAAB3NzaC1kc3MAAACBAMsJAwVWby2y+RLHKm0bGFtZHzZTzoMXLWzjkXVY++a6RlU/oXa3EyKIYse0g/JleqK1oUd+H1Po5/Zs9dimN2H12GWmZmMtbuFonG4jRiSf1dSathzqi3NphUktvtzag0Uas/N9/l8nxR3atXp1ZPR+ejbdlTmyDdtfcvi6zjczAAAAFQDLce5v3see0i7rOPK8OE219obmgQAAAIArgHuPck9ZBXNxj24zoUUjTgHRPr8vp0ufefHZZ1JvrgVvJgcrP+0EwPouGJO+qyyxdD8OTmeVQ9CLJaJd8Avka+FTUbFWJ+eQWCl+GyufAGifH/qvGfVdZWsRn2XTKnujhh4wSUJ/LgKnlSbZLX/sx3LLrYDT3y0HAd1Q1p29VgAAAIEAm1dp9vGhRkeYGkL+ATKVkMJoCOtlncvaBW/Y4pqc6Qxcj0iKKyyImT5fcy1NMaifMNFcawzboiMZgsWC34NbPYFVedXwRwTAlVk3AuBFze2LQgKlZGnlQLLEc1bYv30EA+7VwuYdvzsiumvkAZniq06jRUdJ9YxDM7jWpAa6xgQ= dummy@nowhere 2 | -------------------------------------------------------------------------------- /test-common/src/main/resources/b1024/id_dsa: -------------------------------------------------------------------------------- 1 | -----BEGIN DSA PRIVATE KEY----- 2 | MIIBuwIBAAKBgQCS4Ny6moPe761VpkvIBiIAgSOKnLvTxOTucHNGXUZ4qmqFJ/z1 3 | DAh+BQ/tFCRpQ3qa2fBdiVlOM7qqqlHRogp9d/Fb7w/TENN2Jd6AfJgy+SFzPNfc 4 | TrvOdCs5vcfDIMEJh1aYI+ZIPJ/2GGC7GqJUxxhjHlhmpBIDapizCQ5QjQIVALRs 5 | +1SvZOw1BqIsRDEiStQhdQYHAoGAAuoRj/CSmCkHXuWuEgm3yZ6CVodb6puP/ndI 6 | YTknbcxN8R/Awa5tBIS4PPqTepXVHSNAWjIZIuIV/vMagDpT1kED+4gAxLu2Utvb 7 | N52SvD/c7S79femTOwKK7n6GM/F30GmOBDxDEBxEUifbSpkkuPbjG9SdK3609jYX 8 | NCfvfJECgYADJYhtXZF9HO0ZbB7uT6Xsdkoxwq1r0nfDSpXADYiqirVZvUXovmrM 9 | B30mnKKP49mi/Mp0yWmOKtE2twpZIrKk3JPNx8/SKc+WD0VknlItcetbJrB4FcpE 10 | hUh8wJSL2BdXF/zc7kao2U3xBk5SU7d4jy7X9DOA5ZM/5L5JA1RI+QIVAJr4vPQ0 11 | W4es/SnWBGr0rx/kUNLT 12 | -----END DSA PRIVATE KEY----- 13 | -------------------------------------------------------------------------------- /test-common/src/main/resources/b4096/id_rsa.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC4hXkVxytqXEAjTcu/deBpt0avLH4oxeMj+qvSwuzt4vGXQNQrqnQN1oCZr2y6y5yhXlpvG9j4wgd5SmfF4vSRYvi12ECJdLhh74zJY+9ztDWbkXglpo52RV8QWOj+LzrTqrf+qoSoKxaY5nN0iuRidLArkP3Jc2RZIHgurvLhe2okCk2Qwg275LcV5O71prsAisA30KGjiV+HgT+JctZ7WSX7sxyDPqqHKslpPBGFuXrpVqfsZYQRiGagw6+cAm/sQZzD4gwaHSi1C0sfQPHrQQVv2b5Zt8c47pIOcoKsqSRqfX6liA+yZsftwYkLoitqcWfrMNi5pqE0q1vjjlf41thZlJ/wlcpuQbJho8TCBOe3vHZQzcY2VrrzMI2wXOZLa4loAEJDs69WxJiBLqylhFIl+wZwklLQOaHGenMdKl4eBVaneZU0cPgmHBDWXFsr0KbQXgW8QXxJ3pswVa+FQ3QrKcwCveKOOhwclsSD4DRTwTV62dwOfh0o0G1UEtvJbTFo2NBLjTLL7jL1Fhgbx6yWgTK5p+XnQw5n4H3njSs5A3OLL4eAu81hULvf+UG7DyoDaLosHrfWlYFLb79mCLOubWGgWhqh8F/aMlPoSOLMXoaUsL5WYUkf7dn6hG7TlagxzSc5Rndbm09efiIv91IsaCKZlJyYUfjis96FZQ== dummy@nowhere 2 | -------------------------------------------------------------------------------- /test-common/src/main/resources/withpass/id_dsa: -------------------------------------------------------------------------------- 1 | -----BEGIN DSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: DES-EDE3-CBC,EBF5723C1D1FC5F3 4 | 5 | Xwsdou6X6mxrnXfOYd/QPQzzWIR2LFkm9C5vAJtxJteokIFtZtCNrpsu7OqwAbqE 6 | IQ5xh2nN7JlCJ2mZMDI1QmeM3owmJnfjOx6AWS3k/Zb+yD3/RNZKnKk4xrES2FeV 7 | EFnb+Ln4Gba25eyN3kuk130g7LzQMJB6mFF9cvYyBnp2HHCCvKYrGPHTiyUZqZKi 8 | BPq+OghatMA2s6/iG6dWHssZ8JXOWdaEAhqzfBEvFSFn6avuzCpVakAAxPjcB4Qs 9 | 4l4ZxQg8YfQp69nR12pApr1pbt6dR2AF1xDzVnnpVQ1bOZWTlreleTsMnf5uF9A2 10 | tJbMmxHqogPlMIbqC4vT+Ny8DoWC7pLhmP8b8SQ7GmYFffgxeoxlD8a2LYLmXKOS 11 | ItPAaWkagsweMuowR82uguvvryYoYJffTITDC2csbEN2UUXe0B3VftxKDcLBWsKh 12 | +hmbEVm8TrEIxn8rbxf7HSxp5tPgngCa8x+6e3B+Bo3kz0vhmTr3fjR68o0BUgYp 13 | 89tjaiClNMjQt8vOE9uEuNQcCRcmmXDiufJUCmg8RKSyPWx6N9CChNPYtWnlqlJ4 14 | UUk1lvV+rYMSv5Sy0BHAeA== 15 | -----END DSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /hmac/README.md: -------------------------------------------------------------------------------- 1 | Overview 2 | ======== 3 | 4 | Provides a HMAC implementation with support for SHA-256 and SHA-512. 5 | 6 | 7 | API 8 | === 9 | 10 | Signer 11 | ------ 12 | 13 | To create a Signer, you must provide both a HMAC key and a KeyId. For example: 14 | 15 | Signer signer = new Signer( 16 | new HmacKey("keyId", "ssh. its a secret"), 17 | new HmacKeyId() 18 | ); 19 | 20 | Verifier 21 | -------- 22 | 23 | The Verifier is the mechanism used by a server to verify the signature provided in 24 | the Authorization header against the Request and the Challenge defined for the server. 25 | 26 | To create a Verifier, you must provide a HMAC and a KeyId. For example: 27 | 28 | Verifier verifier = new Verifier( 29 | new DefaultKeychain(Arrays.asList(new HmacKey("keyId", "ssh. its a secret"))), 30 | new HmacKeyId() 31 | ); 32 | -------------------------------------------------------------------------------- /test-common/src/main/resources/b1024/id_rsa: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXAIBAAKBgQC+Fz0pqK+XoCcukPhnPD+M1zb+FImbh5Lu3pkfW5DM67B6Hr9Q 3 | 28LuWgNTfLqUn9o01W0TYzXDxtKG9psGuQ0wFJmqYJNbP6eRB3gimcr+C/eyy7N/ 4 | evs8E36iMi7Si1piPd7QJ5l3D/tThI5cAACHYN0uqwphpXt4Lw2OZxIAQwIDAQAB 5 | AoGAXDx6eRRY34HegUHmxnD9hSGIlZDxlH4cVbu9IPIVONnEL/1rZ5i65VzX8FK9 6 | VhCamLhWzOl+1RhMXyCZ6JEyTCP613Ne/8nsEnPre7QklvEfb2M4imhfxveD4xw4 7 | 4VpH8ZcD75N6h3JSxeCY8DydoDEfxSVSEACnaSpGKt3UlEECQQDkp83/vGipkw/w 8 | p5qeWnKSRUSxOoZTOAEy3sls9K1/L9/kdFYD9qwzigwYvsRy5Ptj16uI1M1T2p0u 9 | yRNgkgD3AkEA1NLKjZyjTKFRPPUdZib46eY0oo4+xF832zENpN1ss7sgRcsHHvtj 10 | AVPH8QE9V8yt8EUn5hBP1k1gCwcxQJh0FQJARJim7zrJt128IXlWpH0D9Ce9tOGW 11 | 3K5nhahai0pYJljpdTMFfwjonkmi2WWZr9JMLKbN+i3FL4vdLeT64DTM/wJBALVf 12 | X1gIYfLwl/dHPeLM290aX0kZyMw6CbQ3vdT/D6CsnPhd6pewzdNXv1HZKJomySW3 13 | CiW7SQ7tqig73PGb+3ECQCifnJsidNZyNklWqS4GMWFzZ+Uyd9p9r5uyIp71ytod 14 | BHCXBAzOi+gWkXtiV7fRXROnOeLdaDWSuUMxG6LuaPI= 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /osgi/src/main/resources/META-INF/NOTICE.txt: -------------------------------------------------------------------------------- 1 | Binary artifacts from the BouncyCastle project are distributed as part of this bundle. 2 | 3 | These artifacts are subject to the following license terms: 4 | 5 | Please note this should be read in the same way as the MIT license. 6 | 7 | LICENSE 8 | 9 | Copyright (c) 2000 - 2013 The Legion of the Bouncy Castle Inc. (http://www.bouncycastle.org) 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 12 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation the 13 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 14 | persons to whom the Software is furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the 17 | Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 20 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 21 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 22 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /api/src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /hmac/src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /osgi/src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /ssh-bc/src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /ssh-jce/src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /ssh-jsch/src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /test-common/src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /http-helpers/src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /api/src/main/java-templates/net/adamcin/httpsig/api/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | @Version("${package-info.version}") 29 | package net.adamcin.httpsig.api; 30 | 31 | import aQute.bnd.annotation.Version; -------------------------------------------------------------------------------- /hmac/src/main/java-templates/net/adamcin/httpsig/hmac/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | @Version("${package-info.version}") 29 | package net.adamcin.httpsig.hmac; 30 | 31 | import aQute.bnd.annotation.Version; 32 | -------------------------------------------------------------------------------- /ssh-bc/src/main/java-templates/net/adamcin/httpsig/ssh/bc/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | @Version("${package-info.version}") 29 | package net.adamcin.httpsig.ssh.bc; 30 | 31 | import aQute.bnd.annotation.Version; -------------------------------------------------------------------------------- /ssh-jce/src/main/java-templates/net/adamcin/httpsig/ssh/jce/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | @Version("${package-info.version}") 29 | package net.adamcin.httpsig.ssh.jce; 30 | 31 | import aQute.bnd.annotation.Version; -------------------------------------------------------------------------------- /ssh-jsch/src/main/java-templates/net/adamcin/httpsig/ssh/jsch/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | @Version("${package-info.version}") 29 | package net.adamcin.httpsig.ssh.jsch; 30 | 31 | import aQute.bnd.annotation.Version; -------------------------------------------------------------------------------- /test-common/src/main/java-templates/net/adamcin/httpsig/testutil/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | @Version("${package-info.version}") 29 | package net.adamcin.httpsig.testutil; 30 | 31 | import aQute.bnd.annotation.Version; -------------------------------------------------------------------------------- /http-helpers/src/main/java-templates/net/adamcin/httpsig/http/ning/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | @Version("${package-info.version}") 29 | package net.adamcin.httpsig.http.ning; 30 | 31 | import aQute.bnd.annotation.Version; -------------------------------------------------------------------------------- /http-helpers/src/main/java-templates/net/adamcin/httpsig/http/apache3/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | @Version("${package-info.version}") 29 | package net.adamcin.httpsig.http.apache3; 30 | 31 | import aQute.bnd.annotation.Version; -------------------------------------------------------------------------------- /http-helpers/src/main/java-templates/net/adamcin/httpsig/http/apache4/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | @Version("${package-info.version}") 29 | package net.adamcin.httpsig.http.apache4; 30 | 31 | import aQute.bnd.annotation.Version; -------------------------------------------------------------------------------- /http-helpers/src/main/java-templates/net/adamcin/httpsig/http/servlet/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | @Version("${package-info.version}") 29 | package net.adamcin.httpsig.http.servlet; 30 | 31 | import aQute.bnd.annotation.Version; -------------------------------------------------------------------------------- /api/src/test/java/net/adamcin/httpsig/api/SignerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | import org.junit.Test; 31 | 32 | public class SignerTest { 33 | 34 | @Test 35 | public void testSign() { 36 | 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /hmac/src/main/java/net/adamcin/httpsig/hmac/HmacKeyId.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.hmac; 29 | 30 | import net.adamcin.httpsig.api.Key; 31 | import net.adamcin.httpsig.api.KeyId; 32 | 33 | public class HmacKeyId implements KeyId { 34 | 35 | public String getId(Key key) { 36 | return key.getId(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test-common/src/main/resources/b2048/id_rsa: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAv/JFXQV93b+oLTZdGGnTTnJqE7FPl0I/bLvUORBogzU0PXe2 3 | 6j1vxXJJOLGu0DQfZQ5bOdOoinZUpYeAHxWK0GgN0dLfiixbQcPmRsoX1Kop90ay 4 | F6LYPVdb//JXhP8cvbUDUSz0/GDdEI9J2oLkZiKdHXpdYFsDOIsgeWQQNmSE4zij 5 | Zs6Qzi+VDrOU2DVj+qMzDWxHVedeUb44gJS89+NjtXURoU/tF1Mea9oquQ+AqHxs 6 | pdgVEzc0yf5yxeaxE7OjU4vOOtx1AvCUNmunfB8TuSwIf9VAQb2Ef9/Piwpw6cwy 7 | pdY/BcAGKYkWbljKPrjGiO2Y6yesAzuHInGfkQIDAQABAoIBAGRxrFiUQhxjaedW 8 | 9nqLDleTyezKMaMuuK/2zoSaEIbwtYig9+g2BCJnvudbG+a6D9+7FoP5Pc5PQ9Zn 9 | ROV/SWfru6ecWPweYBbXI87RfIz+Cv3qUdHKlqvq5irWr3PaaDjh232EMCNNsQE0 10 | ampdapYD8QH3AZwlpFbXf0Pm2BENuu0g7/xGPsdjoAuWOUk+42mmpg/dovd3tJqG 11 | oKzp/38yD/Psw/NQJsXGR+iw95ZRxkeW0EZ8wKRpZjQsbOEL9rWBgTx5emZW1Vg+ 12 | uZL5bJDXrAoHMGojoi88bPEPIigWlBlxFyoM10uumH4kZm/mtr3RO92zWayAlLsM 13 | YQi4XpECgYEA4fukOnDirXY5CBfRA7OtHLPsvFeyLQ6xaHHwVOTOMvsRPy8cYab1 14 | weWsYE47JWhBLUQLenTAa6cbkaqKz6I/1Bkk+hZPi5pW5TZl1SrELyoKvGH/VUBz 15 | kU3qcXPis7iE2PQLqrBAi+gqOyO3aDdFkRr53jcwNHAHcCNyuX5FuTUCgYEA2XE+ 16 | ZOA6OqcfZNkKFAoJ/JS5rPdu2lH/6I46mGAx95UBgTagSgpH8H4WwmxKwBQ0jLIa 17 | SFTeyadFvZxQyrpsg45mgryZa4Mjntb0YySfmSXsn2gM633Be3Rvj9g4iHnfqwZH 18 | AnXm56uUEyukqhW+jAP/sCQP4aoGPYEUYdf3NG0CgYEApadabsCbWb6E9grHW+hV 19 | KOo3yqSaZu8TW1XSb9i90p86uE9nhannEviykHIoZzZyOKVdqKl2+DMqQXB7itML 20 | 6QV5lp3ON66urh1fLpDH+S7fadKIYkz5qnUsO3hQoZ/MOmFDQB8tYaGRe4KmCo4h 21 | v8m/ioZ4HqhUu34wtgr7P1UCgYBVhj4lTTB5+1vUva1CHoS5DQJO7u9x/YirPq37 22 | WvKsT7ZMzWCUXqDXDbED/bYVAJ1+rVq7Em6iYCGFJ6N7aYHe6LaXO3kYmXb8Nc3f 23 | 5PrFMO518GYMheUBGtX6fPAXdeAsk4aAiEEu5ASU2bilkXHl/nimHjkE6GwV6txK 24 | c7hurQKBgAyEnTvqES4OOj7Tij55dvfdjvTQXT4BLiCLeJJCtE5C5Ir8iiodGaL8 25 | 4lmxaJH+3xdO3jm4RouSxsaS7ysGbn6f1Yur6noshhjvaBHvqYkFc7lB37TfDemC 26 | wjv1hZiRB9WyuuIUagtP0xsw9TrE3KKtcJlI4XkB5e8BINPFBNGH 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /api/src/main/java/net/adamcin/httpsig/api/UserKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | /** 31 | * Extends the base {@link Key} interface to add a userId field, which is a common use case for authentication. 32 | * @since 1.0.8 33 | */ 34 | public interface UserKey extends Key { 35 | 36 | /** 37 | * Get the associated userId 38 | * @return the associated userId 39 | */ 40 | String getUserId(); 41 | } 42 | -------------------------------------------------------------------------------- /ssh-jce/src/main/java/net/adamcin/httpsig/ssh/jce/FingerprintableKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.ssh.jce; 29 | 30 | import net.adamcin.httpsig.api.Key; 31 | 32 | /** 33 | * Interface for public keys which can provide a uniquely identifying fingerprint 34 | */ 35 | public interface FingerprintableKey extends Key { 36 | 37 | /** 38 | * @return the public key fingerprint 39 | */ 40 | String getFingerprint(); 41 | } 42 | -------------------------------------------------------------------------------- /api/src/main/java/net/adamcin/httpsig/api/KeyId.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | /** 31 | * Interface used by a {@link Keychain} to generate keyId's from the {@link Key}s that it contains 32 | */ 33 | public interface KeyId { 34 | 35 | /** 36 | * @param key the {@link Key} to identify 37 | * @return the generated keyId or null if the {@link Key} cannot be identified 38 | */ 39 | String getId(Key key); 40 | } 41 | -------------------------------------------------------------------------------- /http-helpers/src/main/java/net/adamcin/httpsig/http/apache3/SignerCredentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.http.apache3; 29 | 30 | import net.adamcin.httpsig.api.Signer; 31 | import org.apache.commons.httpclient.Credentials; 32 | 33 | public final class SignerCredentials implements Credentials { 34 | 35 | private Signer signer; 36 | 37 | public SignerCredentials(Signer signer) { 38 | this.signer = signer; 39 | } 40 | 41 | public Signer getSigner() { 42 | return signer; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /test-common/src/main/resources/withpass/id_rsa: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | Proc-Type: 4,ENCRYPTED 3 | DEK-Info: AES-128-CBC,219E53DC4779367262ED9ABFAD619C91 4 | 5 | ti00939EDp+dv2PCjOJffnj/qFn3vPYyG4pGhJWNTwQkB/py3AT+QJ798IfgwZ8X 6 | jgoRiwGTkAUMV6i52GNcxKsnvaCPH2FMTvzFpTqva+bm0TpLt3XdSKtprf3lidvG 7 | cC3fisE0bZjBshZtyaVON+kGbr+dkRK+3mnylWtpV6Qu6Kyoe8aN6hrqiGohuwzv 8 | jmEIFIelnpf9fzkkt/66TlP2IuXLtKfyD3r+e26+gBj8nI4JA0Maumdfw/XcgDHK 9 | qHJXADBCy/JV2mAL1Jqw6xr0OOLMt7W9NGwHU7PeO8IJns4svpegopVuKLOhtJl9 10 | bAV5eVzwjdFo/kLs7rNz7seC35YAxBaQ5kExl58Y0UgjqatuN57bV34z6MgDC9sS 11 | cRjxfv8xTyajywV1FVdmOHO1kHxmiAuxbhKQa/6tspZftD+8vw43kJiVEfjFWjv8 12 | eWt0melhsmHNDSbLUeHB++/x9SjI7dJXfF4LTJKadKl+cozrU9uNgQ6VgQUyniCq 13 | DE/DsHpaqhnRA7sdPiWJn0w5t4UK11xbUKZTQoIyN1lpuiPup34wmT80fiwZ2+8v 14 | hZMe7RCDdA08i1rwlHYyXcWL72BEGohNyE/DREEOrtPhDsq7ZrLkclwEsOEaRaT5 15 | E/iujg1LNou0clEXOQMfCSsbB0eK0HMbga4kKDM4im4OG6TDWv58YOq/1eV7qQ84 16 | 16TDDgQykpKAhIJz91PE7pA4ged3Q03o0AzJ41W4EyPhjFyWJY4riLOJQRbjUlF+ 17 | Trdx78NEPOcpAixZOqapG6EZK225WPUaroJpA6WcIwNILj4uEeScOlvG0QJgsJHu 18 | 0kiZRIsOE1GbFo4Gi/5zyf+agA0AmvvYR9B4jlLcgjO9wr9YZlpNb9BzeU16qLNu 19 | +FMh+wvphodb6vX3FrW5+qj2XrJyjlv0qj4QlHD9Qx0fZaVLo/nyejE21tCiFgo6 20 | Ca60vv48Cjs8pcmDafi3Bf7e8ah8QSsGH3hYwz3rEf+K4+DKBj51jZ7b6ynHOubT 21 | cnJWwc2JGW0ZpSH6ERrTNdJxmwfMbYaJxmUbykCjJn8BDvGtRYTRJApjX9CJpVmD 22 | JKHJhDNP56F9iD989iaICC+pJnNtBViHu3eIZObWy/eenKzKYTaiyx+IlaAhWi/c 23 | XkJEkN27FaduimDWl2qmvudJRAmGCI5d/TY0yntBzcCaKFsMivULLiKNgtjJg4gh 24 | k1xtRQMOG2eLSbhIxR2+jI5XwbCW0I+VlC7SBRQi0VOk47bB6sDLKrRrBB+NWqLT 25 | 0nSgZUahp2vR5okjHg20aEXIK2Q30sNxm15WEM5g1QTaDkVAX5JL+FSOKrpvUp5U 26 | aUSpE0lagdgP6nhfwpniReoAiYcOYBrKb5Q99TTjh60LpzdyZLPwkcbHmFlnZuSR 27 | PkkyfwCHjvznY8vxZXL1ZhDrVJDVDkYgMn9HskFYvogXRlMPV6+FdLXtLv/+cCxh 28 | U0ZC2KiHV6VgEPgD8ToOFG2Iyd4zQnhhHej0ICvxPzMh5NX9sESfRZE6zAxBXj5V 29 | SpRoCRAXM38mgTaNdh/ELlCKbp1D2lDqdK4at+DmSpVelO3XbD0tvSFJ4oOEtD/g 30 | -----END RSA PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /http-helpers/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 30 | 31 | 32 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /http-helpers/src/main/java/net/adamcin/httpsig/http/apache4/SignerCredentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.http.apache4; 29 | 30 | import net.adamcin.httpsig.api.Signer; 31 | import org.apache.http.auth.Credentials; 32 | 33 | import java.security.Principal; 34 | 35 | public class SignerCredentials implements Credentials { 36 | 37 | private final Signer signer; 38 | 39 | public SignerCredentials(Signer signer) { 40 | this.signer = signer; 41 | } 42 | 43 | public Signer getSigner() { 44 | return signer; 45 | } 46 | 47 | public Principal getUserPrincipal() { 48 | return null; 49 | } 50 | 51 | public String getPassword() { 52 | return null; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/site/xdoc/index.xml: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 30 | 31 | httpsig-java: Implementation of HTTP Signature Authentication in Java 32 | 33 | 34 |
35 |

36 | Visit the Wiki for more information. 37 |

38 | 39 |
    40 |
  • JDK 1.5+ (runtime)
  • 41 |
  • JDK 7+ (tests)
  • 42 |
43 |
44 |
45 | 46 |
47 | -------------------------------------------------------------------------------- /ssh-jce/src/main/java/net/adamcin/httpsig/ssh/jce/UserFingerprintKeyId.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.ssh.jce; 29 | 30 | import net.adamcin.httpsig.api.Key; 31 | import net.adamcin.httpsig.api.KeyId; 32 | 33 | /** 34 | * Implementation of {@link net.adamcin.httpsig.api.KeyId} which incorporates a username into the keyId string. 35 | */ 36 | public final class UserFingerprintKeyId implements KeyId { 37 | private String username; 38 | 39 | public UserFingerprintKeyId(String username) { 40 | this.username = username; 41 | } 42 | 43 | public String getId(Key key) { 44 | if (key instanceof FingerprintableKey) { 45 | return String.format("/%s/%s", username, ((FingerprintableKey) key).getFingerprint()); 46 | } 47 | return null; 48 | } 49 | 50 | public String getUsername() { 51 | return this.username; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /ssh-jce/src/main/java/net/adamcin/httpsig/ssh/jce/UserKeysFingerprintKeyId.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.ssh.jce; 29 | 30 | import net.adamcin.httpsig.api.Key; 31 | import net.adamcin.httpsig.api.KeyId; 32 | 33 | /** 34 | * Implementation of {@link KeyId} following the Joyent API convention of /$username/keys/$fingerprint 35 | * @since 1.0.2 36 | */ 37 | public final class UserKeysFingerprintKeyId implements KeyId { 38 | 39 | private final String username; 40 | 41 | public UserKeysFingerprintKeyId(String username) { 42 | this.username = username; 43 | } 44 | 45 | public String getUsername() { 46 | return username; 47 | } 48 | 49 | public String getId(Key key) { 50 | if (key instanceof FingerprintableKey) { 51 | return String.format("/%s/keys/%s", username, ((FingerprintableKey) key).getFingerprint()); 52 | } 53 | return null; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /api/src/main/java/net/adamcin/httpsig/api/Algorithm.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | /** 31 | * Enumeration of supported HTTP Signature algorithms 32 | */ 33 | public enum Algorithm { 34 | RSA_SHA1("rsa-sha1"), 35 | RSA_SHA256("rsa-sha256"), 36 | RSA_SHA512("rsa-sha512"), 37 | DSA_SHA1("dsa-sha1"), 38 | HMAC_SHA1("hmac-sha1"), 39 | HMAC_SHA256("hmac-sha256"), 40 | HMAC_SHA512("hmac-sha512"), 41 | SSH_RSA("ssh-rsa"), 42 | SSH_DSS("ssh-dss"); 43 | 44 | private final String name; 45 | 46 | private Algorithm(String name) { 47 | this.name = name; 48 | } 49 | 50 | public String getName() { 51 | return name; 52 | } 53 | 54 | public static Algorithm forName(String name) { 55 | for (Algorithm algorithm : Algorithm.values()) { 56 | if (algorithm.getName().equalsIgnoreCase(name)) { 57 | return algorithm; 58 | } 59 | } 60 | 61 | return null; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /test-common/src/main/resources/withpass/id_dsa.properties: -------------------------------------------------------------------------------- 1 | # 2 | # This is free and unencumbered software released into the public domain. 3 | # 4 | # Anyone is free to copy, modify, publish, use, compile, sell, or 5 | # distribute this software, either in source code form or as a compiled 6 | # binary, for any purpose, commercial or non-commercial, and by any 7 | # means. 8 | # 9 | # In jurisdictions that recognize copyright laws, the author or authors 10 | # of this software dedicate any and all copyright interest in the 11 | # software to the public domain. We make this dedication for the benefit 12 | # of the public at large and to the detriment of our heirs and 13 | # successors. We intend this dedication to be an overt act of 14 | # relinquishment in perpetuity of all present and future rights to this 15 | # software under copyright law. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | # OTHER DEALINGS IN THE SOFTWARE. 24 | # 25 | # For more information, please refer to 26 | # 27 | 28 | type=ssh-dss 29 | x=586296799174579389065102658260600942593881550358 30 | g=30548062774699798235002244769370931220068346878521817617622841142972954549558233676330978469285908781455910104730814547494115115869839915978504591351331124542526594556654412739417913176724974129831294467660135104061051953020235083175267499386771442745290329621981187764472744088691628224139883352275946421590 31 | q=1161465881476192974409445020672212051031495206529 32 | p=142576167730513959513353220584296747357072926569290638874796087859068714820964374940060930637084497796255342895715020668797208353549610772545058208582708533886680660443845903746436929371332605325743104371459396942071922089504805515948599294236872274498621979570479742772738298978842918084486168445031059175219 33 | y=109084483341931194117083038269342880427242348064017749372290045172658861097230481150421739681718713128083730866635003132489395514290298753572605019854560470714024559688166944539623253886528828663061652525301177742309018040430253015029979367913404511001439702363174069216806800521309861237110150803707269924356 -------------------------------------------------------------------------------- /test-common/src/main/resources/b1024/id_dsa.properties: -------------------------------------------------------------------------------- 1 | # 2 | # This is free and unencumbered software released into the public domain. 3 | # 4 | # Anyone is free to copy, modify, publish, use, compile, sell, or 5 | # distribute this software, either in source code form or as a compiled 6 | # binary, for any purpose, commercial or non-commercial, and by any 7 | # means. 8 | # 9 | # In jurisdictions that recognize copyright laws, the author or authors 10 | # of this software dedicate any and all copyright interest in the 11 | # software to the public domain. We make this dedication for the benefit 12 | # of the public at large and to the detriment of our heirs and 13 | # successors. We intend this dedication to be an overt act of 14 | # relinquishment in perpetuity of all present and future rights to this 15 | # software under copyright law. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | # OTHER DEALINGS IN THE SOFTWARE. 24 | # 25 | # For more information, please refer to 26 | # 27 | 28 | type=ssh-dss 29 | x=884731623724354687532192689914509818422493237971 30 | g=2046512458836820425298090813288114937752239855893678202112251308478885550662538132074129585438100597392467620688199491752569014013951008953488824129386985052460009006817722533627473425306283264742535663721623020319093171671567173245925884474736031157459854916129960715030751639621852100699362387319189372049 31 | q=1030048713230359034640016789754323868543375181319 32 | p=103141497622699985604422242644387012014929144416942634782059329513196887438997194727800413285185112015108364016417567262514663193675265464722769458694595392602585194786260897117628354332179132438084973649577534460248447251955344103070425439277711962978372257481061620053848500204257930659627432647076019589261 33 | y=2209626766976322824760044094705662692542956817499200011782379995237730070421852881260260841992351411499244978055270219207722466005629638132392522068592957423768378011891160849019460454060764990465960332567122320405823424309375123373521871699299974238393137608277786433057836754621766333452066975942725355769 34 | 35 | -------------------------------------------------------------------------------- /api/src/main/java/net/adamcin/httpsig/api/VerifyResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | /** 31 | * Enumeration of possible results from {@link Verifier#verifyWithResult(Challenge, RequestContent, Authorization)} 32 | */ 33 | public enum VerifyResult { 34 | 35 | /** 36 | * Signature is valid 37 | */ 38 | SUCCESS, 39 | 40 | /** 41 | * {@link Authorization} does not declare all the headers required by the {@link Challenge} 42 | */ 43 | CHALLENGE_NOT_SATISFIED, 44 | 45 | /** 46 | * Not all headers identified by the {@link Authorization} are present in the {@link RequestContent} 47 | */ 48 | INCOMPLETE_REQUEST, 49 | 50 | /** 51 | * The value of the date header falls outside of the current time of the {@link Verifier}, plus or minus the skew 52 | */ 53 | EXPIRED_DATE_HEADER, 54 | 55 | /** 56 | * The {@link Verifier} cannot find a {@link Key} matching the keyId of the {@link Authorization} 57 | */ 58 | KEY_NOT_FOUND, 59 | 60 | /** 61 | * The selected {@link Key} rejected the signature as invalid 62 | */ 63 | FAILED_KEY_VERIFY 64 | } 65 | -------------------------------------------------------------------------------- /api/src/test/java/net/adamcin/httpsig/api/RequestContentTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | import org.junit.Test; 31 | 32 | import java.util.Arrays; 33 | import java.util.List; 34 | 35 | import static org.junit.Assert.*; 36 | 37 | public class RequestContentTest { 38 | 39 | /** 40 | * Added for defect-1, provided test case: "Fri Jun 20 10:11:40 2014 GMT" 41 | */ 42 | @Test 43 | public void testTryParseDate() { 44 | List nonDates = Arrays.asList("not a date", null, "", "Abc Def 20 10:11:40 2014 XUL"); 45 | for (String nonDate : nonDates) { 46 | assertFalse("non-dates should fail the check: " + nonDate, RequestContent.tryParseDate(nonDate) != null); 47 | } 48 | 49 | List dates = Arrays.asList( 50 | "Fri Jun 1 10:11:40 2014 GMT", 51 | "Fri Jun 20 10:11:40 2014 GMT", 52 | "Thu, 01 Dec 1994 16:00:00 GMT", 53 | "Tue, 07 Jun 2014 20:51:35 GMT" 54 | ); 55 | for (String date : dates) { 56 | assertTrue("real dates should pass the check: " + date, RequestContent.tryParseDate(date) != null); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /api/src/test/java/net/adamcin/httpsig/api/Base64Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | import org.junit.Test; 31 | 32 | import static org.apache.commons.codec.binary.Base64.decodeBase64; 33 | import static org.apache.commons.codec.binary.Base64.encodeBase64; 34 | import static org.junit.Assert.*; 35 | 36 | 37 | public class Base64Test { 38 | 39 | @Test 40 | public void testTo() { 41 | 42 | byte[] foobarBytes = "foobar".getBytes(); 43 | assertEquals( 44 | "foobar should be encoded the same way as in commons-codec", 45 | new String(encodeBase64(foobarBytes, false), Constants.CHARSET), 46 | Base64.toBase64String(foobarBytes) 47 | ); 48 | } 49 | 50 | @Test 51 | public void testFrom() { 52 | byte[] foobarBytes = "foobar".getBytes(); 53 | String encoded = new String(encodeBase64(foobarBytes, false), Constants.CHARSET); 54 | 55 | assertEquals("foobar (encoded) should be decoded the same way as in commons-codec", 56 | new String(decodeBase64(encoded.getBytes(Constants.CHARSET))), 57 | new String(Base64.fromBase64String(encoded))); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /test-common/src/main/resources/b1024/id_rsa.properties: -------------------------------------------------------------------------------- 1 | # 2 | # This is free and unencumbered software released into the public domain. 3 | # 4 | # Anyone is free to copy, modify, publish, use, compile, sell, or 5 | # distribute this software, either in source code form or as a compiled 6 | # binary, for any purpose, commercial or non-commercial, and by any 7 | # means. 8 | # 9 | # In jurisdictions that recognize copyright laws, the author or authors 10 | # of this software dedicate any and all copyright interest in the 11 | # software to the public domain. We make this dedication for the benefit 12 | # of the public at large and to the detriment of our heirs and 13 | # successors. We intend this dedication to be an overt act of 14 | # relinquishment in perpetuity of all present and future rights to this 15 | # software under copyright law. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | # OTHER DEALINGS IN THE SOFTWARE. 24 | # 25 | # For more information, please refer to 26 | # 27 | 28 | type=ssh-rsa 29 | n=133486283143772040859788174111963333609575575060209439712010001020815160542569663681077372185412102667429777324231031767877049049124926796091059441882104574820379819312266978480602058944405851943552003429781749528257750596964185034984234791531548409086043651587904593977019849230775014185535208710865073340483 30 | e=65537 31 | d=64770493064558202226852982845727360251224549291463756089566474395561623285376433237076162099212732728447547475632799948403041942142189482516680504933868268977897716797842773630590451195044581018482899945345230667316230249883524234556770017311730675629793025629626484746888091910266659323396639630856553796673 32 | p=11975659579782362027580210448929024938661300498458117784047207198411406458542643481913792399962342620695439639616602348026135827061725884849581267264602359 33 | q=11146466067650023760478127257815077872206518366175497601259544143950129533795480783172564340481688399512101446394643325757701138328180485404051376237474837 34 | pe=3592679600807193185898874187655729730061184202819553134140289313333943610195872766496895988154166627485131128286342352633502548115729933045876639084629247 35 | qe=9499251152942446664788201528960552501922249474154048736218442399375965252018633637513985436388349489441840334223928758262037077954522429631919029946678129 36 | u=2127624462660802112477216493624681148115703392727281796410101685773436094351689593770284594119099384642510131149153994091208822196462657793051284722313458 -------------------------------------------------------------------------------- /api/src/main/java/net/adamcin/httpsig/api/Keychain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | import java.util.Collection; 31 | import java.util.Map; 32 | import java.util.Set; 33 | 34 | /** 35 | * Immutable interface for a list of {@link Key}s 36 | */ 37 | public interface Keychain extends Iterable { 38 | 39 | /** 40 | * @return a {@link Set} containing the union of all algorithms supported by each {@link Key} in this {@link Keychain} 41 | */ 42 | Set getAlgorithms(); 43 | 44 | /** 45 | * Filter this keychain by a {@link Collection} of supported {@link Algorithm}s 46 | * @param algorithms supported algorithms 47 | * @return a new {@link Keychain} containing only those keys which support at least one of the provided algorithms 48 | */ 49 | Keychain filterAlgorithms(Collection algorithms); 50 | 51 | /** 52 | * @return a reference to a {@link Keychain} which excludes the current {@link Key}. 53 | */ 54 | Keychain discard(); 55 | 56 | /** 57 | * @return a reference to the current {@link Key}. 58 | */ 59 | Key currentKey(); 60 | 61 | /** 62 | * @param keyId the KeyId 63 | * @return a {@link Map} where the values are the {@link Key}s and the map entry keys are the keyId's generated by the {@link KeyId} 64 | */ 65 | Map toMap(KeyId keyId); 66 | 67 | /** 68 | * @return true if this {@link Keychain} has no more keys 69 | */ 70 | boolean isEmpty(); 71 | } 72 | -------------------------------------------------------------------------------- /api/src/test/java/net/adamcin/httpsig/api/MockKey.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | import java.util.Arrays; 31 | import java.util.HashSet; 32 | import java.util.Set; 33 | 34 | public class MockKey implements Key { 35 | 36 | String fingerprint = null; 37 | 38 | public MockKey(String fingerprint) { 39 | this.fingerprint = fingerprint; 40 | } 41 | 42 | public String getId() { 43 | return fingerprint; 44 | } 45 | 46 | public boolean canVerify() { 47 | return true; 48 | } 49 | 50 | public boolean canSign() { 51 | return true; 52 | } 53 | 54 | public boolean verify(Algorithm algorithm, byte[] challengeHash, byte[] signatureBytes) { 55 | return new StringBuilder(new String(signatureBytes, Constants.CHARSET)).reverse().toString().equals(new String(challengeHash, Constants.CHARSET)); 56 | } 57 | 58 | public byte[] sign(Algorithm algorithm, byte[] challengeHash) { 59 | return mockSign(challengeHash); 60 | } 61 | 62 | public static byte[] mockSign(byte[] challengeHash) { 63 | return new StringBuilder(new String(challengeHash, Constants.CHARSET)).reverse().toString().getBytes(Constants.CHARSET); 64 | } 65 | 66 | public static String mockSignBase64(byte[] challengeHash) { 67 | return Base64.toBase64String(mockSign(challengeHash)); 68 | } 69 | 70 | public Set getAlgorithms() { 71 | return new HashSet(Arrays.asList(Algorithm.values())); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /test-common/src/main/resources/authorized_keys: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC+Fz0pqK+XoCcukPhnPD+M1zb+FImbh5Lu3pkfW5DM67B6Hr9Q28LuWgNTfLqUn9o01W0TYzXDxtKG9psGuQ0wFJmqYJNbP6eRB3gimcr+C/eyy7N/evs8E36iMi7Si1piPd7QJ5l3D/tThI5cAACHYN0uqwphpXt4Lw2OZxIAQw== dummy@nowhere 2 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/8kVdBX3dv6gtNl0YadNOcmoTsU+XQj9su9Q5EGiDNTQ9d7bqPW/Fckk4sa7QNB9lDls506iKdlSlh4AfFYrQaA3R0t+KLFtBw+ZGyhfUqin3RrIXotg9V1v/8leE/xy9tQNRLPT8YN0Qj0naguRmIp0del1gWwM4iyB5ZBA2ZITjOKNmzpDOL5UOs5TYNWP6ozMNbEdV515RvjiAlLz342O1dRGhT+0XUx5r2iq5D4CofGyl2BUTNzTJ/nLF5rETs6NTi8463HUC8JQ2a6d8HxO5LAh/1UBBvYR/38+LCnDpzDKl1j8FwAYpiRZuWMo+uMaI7ZjrJ6wDO4cicZ+R dummy@nowhere 3 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC4hXkVxytqXEAjTcu/deBpt0avLH4oxeMj+qvSwuzt4vGXQNQrqnQN1oCZr2y6y5yhXlpvG9j4wgd5SmfF4vSRYvi12ECJdLhh74zJY+9ztDWbkXglpo52RV8QWOj+LzrTqrf+qoSoKxaY5nN0iuRidLArkP3Jc2RZIHgurvLhe2okCk2Qwg275LcV5O71prsAisA30KGjiV+HgT+JctZ7WSX7sxyDPqqHKslpPBGFuXrpVqfsZYQRiGagw6+cAm/sQZzD4gwaHSi1C0sfQPHrQQVv2b5Zt8c47pIOcoKsqSRqfX6liA+yZsftwYkLoitqcWfrMNi5pqE0q1vjjlf41thZlJ/wlcpuQbJho8TCBOe3vHZQzcY2VrrzMI2wXOZLa4loAEJDs69WxJiBLqylhFIl+wZwklLQOaHGenMdKl4eBVaneZU0cPgmHBDWXFsr0KbQXgW8QXxJ3pswVa+FQ3QrKcwCveKOOhwclsSD4DRTwTV62dwOfh0o0G1UEtvJbTFo2NBLjTLL7jL1Fhgbx6yWgTK5p+XnQw5n4H3njSs5A3OLL4eAu81hULvf+UG7DyoDaLosHrfWlYFLb79mCLOubWGgWhqh8F/aMlPoSOLMXoaUsL5WYUkf7dn6hG7TlagxzSc5Rndbm09efiIv91IsaCKZlJyYUfjis96FZQ== dummy@nowhere 4 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDwm2QdZogDqbOgG5KQgpQdDkb1iAIeH5Q3GOvr+LHtWWUxugdxk11yI28fO8WxAkg8gSTetJR9PQT0rvVIWZdjHpFhyLOiPpSz3+QkfPFilh7caPILfcLqivqmx4JMHXkMppn1u1n4ITbP/ZCaswX5S/zkEkGtBM/+3ckNlmxAEuaOJR1tXmdE9IiD6vPIIs9TeOYVkmpl17LTL82nKscOo1Wbof6MkuAeQutJJ6YFMWJSwx0kzAN5XSTrJvndArsCHayl4JTDNkkGj2wHMEh14MsMn+5/nbAN1xxpD4vfqG0k03dYFvk1EGhcWobBN6F/Pt7NWpZUaAdZ39wMTMH1 dummy@nowhere 5 | ssh-dss AAAAB3NzaC1kc3MAAACBAJLg3Lqag97vrVWmS8gGIgCBI4qcu9PE5O5wc0ZdRniqaoUn/PUMCH4FD+0UJGlDeprZ8F2JWU4zuqqqUdGiCn138VvvD9MQ03Yl3oB8mDL5IXM819xOu850Kzm9x8MgwQmHVpgj5kg8n/YYYLsaolTHGGMeWGakEgNqmLMJDlCNAAAAFQC0bPtUr2TsNQaiLEQxIkrUIXUGBwAAAIAC6hGP8JKYKQde5a4SCbfJnoJWh1vqm4/+d0hhOSdtzE3xH8DBrm0EhLg8+pN6ldUdI0BaMhki4hX+8xqAOlPWQQP7iADEu7ZS29s3nZK8P9ztLv196ZM7AorufoYz8XfQaY4EPEMQHERSJ9tKmSS49uMb1J0rfrT2Nhc0J+98kQAAAIADJYhtXZF9HO0ZbB7uT6Xsdkoxwq1r0nfDSpXADYiqirVZvUXovmrMB30mnKKP49mi/Mp0yWmOKtE2twpZIrKk3JPNx8/SKc+WD0VknlItcetbJrB4FcpEhUh8wJSL2BdXF/zc7kao2U3xBk5SU7d4jy7X9DOA5ZM/5L5JA1RI+Q== dummy@nowhere 6 | ssh-dss AAAAB3NzaC1kc3MAAACBAMsJAwVWby2y+RLHKm0bGFtZHzZTzoMXLWzjkXVY++a6RlU/oXa3EyKIYse0g/JleqK1oUd+H1Po5/Zs9dimN2H12GWmZmMtbuFonG4jRiSf1dSathzqi3NphUktvtzag0Uas/N9/l8nxR3atXp1ZPR+ejbdlTmyDdtfcvi6zjczAAAAFQDLce5v3see0i7rOPK8OE219obmgQAAAIArgHuPck9ZBXNxj24zoUUjTgHRPr8vp0ufefHZZ1JvrgVvJgcrP+0EwPouGJO+qyyxdD8OTmeVQ9CLJaJd8Avka+FTUbFWJ+eQWCl+GyufAGifH/qvGfVdZWsRn2XTKnujhh4wSUJ/LgKnlSbZLX/sx3LLrYDT3y0HAd1Q1p29VgAAAIEAm1dp9vGhRkeYGkL+ATKVkMJoCOtlncvaBW/Y4pqc6Qxcj0iKKyyImT5fcy1NMaifMNFcawzboiMZgsWC34NbPYFVedXwRwTAlVk3AuBFze2LQgKlZGnlQLLEc1bYv30EA+7VwuYdvzsiumvkAZniq06jRUdJ9YxDM7jWpAa6xgQ= dummy@nowhere 7 | -------------------------------------------------------------------------------- /http-helpers/src/main/java/net/adamcin/httpsig/http/apache3/SignerCredentialsProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.http.apache3; 29 | 30 | import net.adamcin.httpsig.api.Constants; 31 | import net.adamcin.httpsig.api.Signer; 32 | import org.apache.commons.httpclient.Credentials; 33 | import org.apache.commons.httpclient.auth.AuthScheme; 34 | import org.apache.commons.httpclient.auth.CredentialsNotAvailableException; 35 | import org.apache.commons.httpclient.auth.CredentialsProvider; 36 | 37 | public final class SignerCredentialsProvider implements CredentialsProvider { 38 | 39 | private final Signer signer; 40 | private final CredentialsProvider delegatee; 41 | 42 | public SignerCredentialsProvider(Signer signer, CredentialsProvider delegatee) { 43 | this.signer = signer; 44 | this.delegatee = delegatee; 45 | } 46 | 47 | public CredentialsProvider getDelegatee() { 48 | return delegatee; 49 | } 50 | 51 | public Credentials getCredentials(AuthScheme scheme, String host, int port, boolean proxy) 52 | throws CredentialsNotAvailableException { 53 | 54 | if (Constants.SCHEME.equals(scheme.getSchemeName())) { 55 | if (signer == null) { 56 | throw new CredentialsNotAvailableException("SSHKey Signer not available"); 57 | } else { 58 | return new SignerCredentials(signer); 59 | } 60 | } else { 61 | if (this.delegatee != null) { 62 | return this.delegatee.getCredentials(scheme, host, port, proxy); 63 | } 64 | } 65 | return null; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /http-helpers/src/main/java/net/adamcin/httpsig/http/ning/AsyncSignatureCalculator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.http.ning; 29 | 30 | import com.ning.http.client.Request; 31 | import com.ning.http.client.RequestBuilderBase; 32 | import com.ning.http.client.SignatureCalculator; 33 | import net.adamcin.httpsig.api.Signer; 34 | 35 | /** 36 | * Implementation of {@link SignatureCalculator} using a {@link Signer} 37 | */ 38 | public class AsyncSignatureCalculator implements SignatureCalculator { 39 | private static final SignatureCalculator DEFAULT_DELEGATEE = new SignatureCalculator() { 40 | @Override 41 | public void calculateAndAddSignature(Request request, RequestBuilderBase requestBuilder) { } 42 | }; 43 | 44 | private final Signer signer; 45 | private final SignatureCalculator delegatee; 46 | 47 | public AsyncSignatureCalculator(Signer signer) { 48 | this(signer, null); 49 | } 50 | 51 | public AsyncSignatureCalculator(Signer signer, SignatureCalculator delegatee) { 52 | this.signer = signer; 53 | this.delegatee = delegatee != null ? delegatee : DEFAULT_DELEGATEE; 54 | } 55 | 56 | /** 57 | * {@inheritDoc} 58 | */ 59 | public void calculateAndAddSignature(String url, Request request, RequestBuilderBase requestBuilder) { 60 | this.calculateAndAddSignature(request, requestBuilder); 61 | } 62 | 63 | @Override 64 | public void calculateAndAddSignature(Request request, RequestBuilderBase requestBuilder) { 65 | delegatee.calculateAndAddSignature(request, requestBuilder); 66 | AsyncUtil.calculateSignature(this.signer, request, requestBuilder); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /http-helpers/src/main/java/net/adamcin/httpsig/http/apache4/Http4Util.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.http.apache4; 29 | 30 | import net.adamcin.httpsig.api.Constants; 31 | import net.adamcin.httpsig.api.KeyId; 32 | import net.adamcin.httpsig.api.Keychain; 33 | import net.adamcin.httpsig.api.Signer; 34 | import org.apache.http.auth.AuthScheme; 35 | import org.apache.http.auth.AuthSchemeFactory; 36 | import org.apache.http.auth.AuthScope; 37 | import org.apache.http.auth.params.AuthPNames; 38 | import org.apache.http.client.params.HttpClientParams; 39 | import org.apache.http.impl.client.AbstractHttpClient; 40 | import org.apache.http.params.HttpParams; 41 | 42 | import java.util.Arrays; 43 | 44 | public final class Http4Util { 45 | 46 | public static void enableAuth(final AbstractHttpClient client, final Keychain keychain, final KeyId keyId) { 47 | if (client == null) { 48 | throw new NullPointerException("client"); 49 | } 50 | 51 | if (keychain == null) { 52 | throw new NullPointerException("keychain"); 53 | } 54 | 55 | client.getAuthSchemes().register(Constants.SCHEME, new AuthSchemeFactory() { 56 | public AuthScheme newInstance(HttpParams params) { 57 | return new Http4SignatureAuthScheme(); 58 | } 59 | }); 60 | 61 | Signer signer = new Signer(keychain, keyId); 62 | client.getCredentialsProvider().setCredentials(AuthScope.ANY, new SignerCredentials(signer)); 63 | client.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF, 64 | Arrays.asList(Constants.SCHEME)); 65 | 66 | HttpClientParams.setAuthenticating(client.getParams(), true); 67 | } 68 | 69 | private Http4Util() { 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /ssh-bc/src/test/java/net/adamcin/httpsig/ssh/bc/PEMUtilTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.ssh.bc; 29 | 30 | import net.adamcin.commons.testing.junit.FailUtil; 31 | import net.adamcin.httpsig.api.Key; 32 | import net.adamcin.httpsig.ssh.jce.FingerprintableKey; 33 | import net.adamcin.httpsig.ssh.jce.KeyFormat; 34 | import net.adamcin.httpsig.ssh.jce.SSHKey; 35 | import net.adamcin.httpsig.testutil.KeyTestUtil; 36 | import org.junit.Test; 37 | 38 | import java.io.IOException; 39 | import java.security.KeyPair; 40 | 41 | import static org.junit.Assert.*; 42 | 43 | /** 44 | */ 45 | public class PEMUtilTest { 46 | 47 | @Test 48 | public void testReadKey() { 49 | KeyPair keyPair = KeyTestUtil.getKeyPairFromProperties("b2048", "id_rsa"); 50 | SSHKey sshKey = new SSHKey(KeyFormat.SSH_RSA, keyPair); 51 | 52 | try { 53 | Key bcKey = PEMUtil.readKey(KeyTestUtil.getPrivateKeyAsFile("b2048", "id_rsa"), null); 54 | 55 | assertEquals("fingerprints should match", sshKey.getFingerprint(), ((FingerprintableKey) bcKey).getFingerprint()); 56 | } catch (IOException e) { 57 | FailUtil.sprintFail(e); 58 | } 59 | } 60 | 61 | @Test 62 | public void testEncryptedKey() { 63 | KeyPair keyPair = KeyTestUtil.getKeyPairFromProperties("withpass", "id_rsa"); 64 | SSHKey sshKey = new SSHKey(KeyFormat.SSH_RSA, keyPair); 65 | 66 | try { 67 | Key bcKey = PEMUtil.readKey(KeyTestUtil.getPrivateKeyAsFile("withpass", "id_rsa"), "dummydummy".toCharArray()); 68 | 69 | assertEquals("fingerprints should match", sshKey.getFingerprint(), ((FingerprintableKey) bcKey).getFingerprint()); 70 | } catch (IOException e) { 71 | FailUtil.sprintFail(e); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /api/src/main/java/net/adamcin/httpsig/api/Key.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | import java.util.Set; 31 | 32 | /** 33 | * Interface representing an object which can sign content and/or verify signatures 34 | */ 35 | public interface Key { 36 | 37 | /** 38 | * @return the {@link Key}'s self-identification. This may end up not being unique within a keychain. 39 | */ 40 | String getId(); 41 | 42 | /** 43 | * @return the {@link Set} of Signature {@link Algorithm}s supported by this key. 44 | */ 45 | Set getAlgorithms(); 46 | 47 | /** 48 | * @return true if this {@link Key} can be used for verification 49 | */ 50 | boolean canVerify(); 51 | 52 | /** 53 | * Verifies the {@code signatureBytes} against the {@code challengeHash} using an underlying public key 54 | * @param algorithm the selected Signature {@link Algorithm} 55 | * @param contentBytes the result of {@link RequestContent#getBytesToSign(java.util.List, java.nio.charset.Charset)} 56 | * @param signatureBytes the result of {@link net.adamcin.httpsig.api.Authorization#getSignatureBytes()} 57 | * @return true if signature is valid 58 | */ 59 | boolean verify(Algorithm algorithm, byte[] contentBytes, byte[] signatureBytes); 60 | 61 | /** 62 | * @return true if this {@link Key} can be used for signing 63 | */ 64 | boolean canSign(); 65 | 66 | /** 67 | * Signs the {@code challengeHash} using the specified signature {@link Algorithm} 68 | * @param algorithm the selected Signature {@link Algorithm} 69 | * @param contentBytes the result of {@link RequestContent#getBytesToSign(java.util.List, java.nio.charset.Charset)} 70 | * @return byte array containing the challengeHash signature or null if a signature could not be generated. 71 | */ 72 | byte[] sign(Algorithm algorithm, byte[] contentBytes); 73 | } 74 | -------------------------------------------------------------------------------- /api/src/test/java/net/adamcin/httpsig/api/MockKeychain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | import java.util.Arrays; 31 | import java.util.Collection; 32 | import java.util.Collections; 33 | import java.util.HashSet; 34 | import java.util.Iterator; 35 | import java.util.Map; 36 | import java.util.Set; 37 | 38 | /** 39 | * 40 | */ 41 | public class MockKeychain implements Keychain { 42 | 43 | private MockKey mockIdentity; 44 | 45 | public MockKeychain(String fingerprint) { 46 | this.mockIdentity = new MockKey(fingerprint); 47 | } 48 | 49 | public Key findKey(String fingerprint) { 50 | if (fingerprint != null && fingerprint.equals(mockIdentity.getId())) { 51 | return mockIdentity; 52 | } 53 | return null; 54 | } 55 | 56 | public Set getKeyIds() { 57 | return Collections.unmodifiableSet(new HashSet(Arrays.asList(mockIdentity.getId()))); 58 | } 59 | 60 | public Set getAlgorithms() { 61 | return mockIdentity != null ? mockIdentity.getAlgorithms() : Collections.emptySet(); 62 | } 63 | 64 | public Keychain discard() { 65 | return new DefaultKeychain(); 66 | } 67 | 68 | public Key currentKey() { 69 | return this.mockIdentity; 70 | } 71 | 72 | public boolean isEmpty() { 73 | return this.mockIdentity != null; 74 | } 75 | 76 | public Keychain filterAlgorithms(Collection algorithms) { 77 | throw new UnsupportedOperationException("filterAlgorithms not implemented"); 78 | } 79 | 80 | public Map toMap(KeyId keyId) { 81 | return Collections.singletonMap(keyId != null ? 82 | keyId.getId(this.mockIdentity) : this.mockIdentity.getId(), 83 | this.mockIdentity); 84 | } 85 | 86 | public Iterator iterator() { 87 | return Collections.singletonList(mockIdentity).iterator(); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /test-common/src/main/resources/b4096/id_rsa: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIJJwIBAAKCAgEAuIV5FccralxAI03Lv3XgabdGryx+KMXjI/qr0sLs7eLxl0DU 3 | K6p0DdaAma9susucoV5abxvY+MIHeUpnxeL0kWL4tdhAiXS4Ye+MyWPvc7Q1m5F4 4 | JaaOdkVfEFjo/i8606q3/qqEqCsWmOZzdIrkYnSwK5D9yXNkWSB4Lq7y4XtqJApN 5 | kMINu+S3FeTu9aa7AIrAN9Cho4lfh4E/iXLWe1kl+7Mcgz6qhyrJaTwRhbl66Van 6 | 7GWEEYhmoMOvnAJv7EGcw+IMGh0otQtLH0Dx60EFb9m+WbfHOO6SDnKCrKkkan1+ 7 | pYgPsmbH7cGJC6IranFn6zDYuaahNKtb445X+NbYWZSf8JXKbkGyYaPEwgTnt7x2 8 | UM3GNla68zCNsFzmS2uJaABCQ7OvVsSYgS6spYRSJfsGcJJS0DmhxnpzHSpeHgVW 9 | p3mVNHD4JhwQ1lxbK9Cm0F4FvEF8Sd6bMFWvhUN0KynMAr3ijjocHJbEg+A0U8E1 10 | etncDn4dKNBtVBLbyW0xaNjQS40yy+4y9RYYG8esloEyuafl50MOZ+B9540rOQNz 11 | iy+HgLvNYVC73/lBuw8qA2i6LB631pWBS2+/Zgizrm1hoFoaofBf2jJT6EjizF6G 12 | lLC+VmFJH+3Z+oRu05WoMc0nOUZ3W5tPXn4iL/dSLGgimZScmFH44rPehWUCAwEA 13 | AQKCAgAjxXRY3Xi0MNgaP/2sy0xLEkW4tfZrLxm+otzmifVmlKVjPiUjpfLDr/7U 14 | TGbWu5xMyD7d5Vclum+6esstWLcy7C3tCtRQEXmhOtBfRmloU9pEo2nYWraphP9N 15 | 6v6YME3GNQVgcGwxMdE6qQpe4IIv+BEjEQOyJxWgFaRW4IGjZsqH3Bt3YbdJ4qf/ 16 | rZcJtl3wV/W1nFOJoZsMaOkJW2LrHLg5WFrBssdaVtge948qDnAehjcdo/x7bab/ 17 | qZAEvZA3C+05KDxSX67BkkPo9i0v/zXvnhXBzNfpWI6mEFr23/94SYXgz0TDwBso 18 | I2nPAIxMIVoVBS4up3f+/u1cav7woPX1FWJza4GBDTRDo691+lGxc1hw49LbHbQ4 19 | +2hF0IQe5R/6uemxzDYwJA8AeaJAjpIgqbuqWmt7GsKa38f+0J+d6y3Y9xojQU0o 20 | TLTg7FVKLHslRYnIOeBQ07oOg3zMrtNSK+ayF5H9HPqHQM8tLlmNF/pwjG3aoCH1 21 | 1A5qjiTb79r3YdKM3vEayN9nnD9rzOhEVpxFtljYjRQaNGoaWnmPj5cgOvjrcJA7 22 | g8cYKISnqwzJG9GMqFQ0ui4fT8S9acE0IvBp7hCtFhLIAAGZvrUGmk7GdS+tHTpr 23 | qC8OPMsZj0J9SThu89+JQsygAqcw5H6u8Gf6gX3VgpLcrcTtgQKCAQEA8PqoMlqX 24 | rsvWgAAF09Ekm03B8DGo8YGjBoHo0DbDVn5NXEyhHMQCDxC8GFDUs/h7ejAEMu0g 25 | WvM9nLnNOqXKjO5gplMqj2Dd9N90LmyrOhpidyyYh7HREraGOYU1rtOIiERkFLOU 26 | lkGtsD8cdBZXdi9PzWu9tzLJpdVv8p4MnuqPK3p5PvDiwWw77x2okyDu2Mruq312 27 | BtDcdXxyBYSnYv0ROiYOFPcaUwfG/KZHhWcvephZbNHXEvbrMFS6uecH5JjNov/4 28 | 1T4aeh1Q9d3PXQGIVA/qyz4gR8z8o/G2Y5Zri4/wsc5lsKBaR23WKklVNrmQeLtn 29 | 9WbKAdlZbCszYQKCAQEAxAXpFymqbaKjoW5RGAEfMz6bU1+Co41RB7zyH6ytib4F 30 | z+jwCUPebbZaeLbjdGHen5bAuVzp0IiL26M16WdF/SiFMsUaH2WtR7gvziTZ2KR5 31 | 7LQnLg7Pe+ThkOsi5k3O/9DflGxQIGnLbCZhaSJ6FH17C6y2fRq63GtOmO8AmIaI 32 | uYvALFx72PldcRC8P3Gaa022chi3QUeuGLHUzLjBsc8CLyo7CAsptYcyuCJ+FaiH 33 | wgRpmBLMQMo6O4xTf4qGwKeQfeH4JdgX29D4xKkAB8/Uhsx8PQcbQyS2FgxTSKdv 34 | lpi3guvasSH1c+vK4DmU3CEDR8faXWpBUYGJ3zFUhQKCAQAG2alEXSzorCS52MZR 35 | oiVfQNOdh1vdGalPuwuqN5RP9iEu2YLO9Yd1dC1Up5+USiEAdTL5W6JK05VRyjpa 36 | S3I5lWEr+TtBfihxGJUN6MrpSOy5pIvld5mQ5Z1lLzM6eArujLsnl39G0jEkzHZ7 37 | mlL8KhYjqcdn2MrAqxOWmwWS0uok+0NNFb3sb644euha3lnL0eD9AQEE6pUJxfLb 38 | 00yK1NTTiVdnIysdZyAx+GwaD7fazU/ldwWdJWXEJvRz6mxgBDP8STiCn1RTWlf9 39 | 1UNayntcoGM1SdvTDrGz22Aq7pC6E+pss4hSgAxw8V9gLlt8xcOkmvc2k6h0awBO 40 | wd+hAoIBABUg7fbpLs2SckC8O1FzDYHgha1+5f3rBYjn/NEdM7ddHBNE8FqPTjJV 41 | LXtFe07YHb7l6PAR68Hmdey+stjtoMWg0HqgdCheNUc9uyllH3YShHHXGUIFpqec 42 | DBQqxCA+0skQIolFA3366UpG+Mj0RmRfAhxICYOClhGcH2SsnkvSdHpLbfNaJJ9G 43 | gaPmQeQ0wog+YCP8NgR7TXCr+lv2rioUPhAHZUWAroY6hGUEksKS388x2o/httJk 44 | +dHhVj6xF8U8Sn7HFJA/spKm+6l27eHprOa6s8mAMpgSJO5Ldc6m/Ygl/eHGulPN 45 | bT+JctyoWDtB87CRAiB/i3rVk57TGmECggEAfZlNC4FyHbWRJ0hWRdn7Iw8jC8rd 46 | QGa4ulTIjBcG8ClFBPiOK/ua+EY5U0o9Wg7DCN63CcDZicT91DDFhzWLt0mAZ2jf 47 | FJKjciVQIi1wyvbaYvfDDvjBl3nn01VoqG0JzoA+t2y9fNF9hsVDtLGli0aGEQ8O 48 | leqoH76ySWyN0lKAQC2/xnJqpSumc3MQC7S5jOFx4purEFd4ATQXG69c918q+nb2 49 | J8mr+0JqtsqaLP1k4LK6rPkVeUIpp/0LWRQjQsfVdYamwp8xMJEU8PbAu+/Rmu50 50 | FCEqLJcTU3ucnM5/9rs65Ba+pH9xQjbJqkay3I1Ao62m8IjRShUBCPQwAg== 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /api/src/main/java/net/adamcin/httpsig/api/Verifier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | /** 31 | * Limited interface allowing for server-side use of guards and remote service calls 32 | * @since 1.0.8 33 | */ 34 | public interface Verifier { 35 | 36 | /** 37 | * @return server skew in milliseconds 38 | */ 39 | long getSkew(); 40 | 41 | /** 42 | * Selects an appropriate {@link Key} from the {@link Keychain} matching the keyId specified in the 43 | * {@link Authorization}. This method is called by 44 | * {@link #verifyWithResult(Challenge, RequestContent, Authorization)}, but can be called by client code to 45 | * retrieve the identified {@link Key} directly 46 | * @since 1.0.6 47 | * @param authorization the {@link Authorization} header 48 | * @return a matching {@link Key} or null 49 | */ 50 | Key selectKey(Authorization authorization); 51 | 52 | /** 53 | * Verifies the provided {@link Authorization} header against the original {@link Challenge} 54 | * @param challenge the WWW-Authenticate challenge sent to the client in the previous response 55 | * @param requestContent the {@link RequestContent} containing the request header content 56 | * @param authorization the {@link Authorization} header to verify 57 | * @return true if valid ({@link VerifyResult#SUCCESS}), false otherwise 58 | */ 59 | boolean verify(Challenge challenge, RequestContent requestContent, Authorization authorization); 60 | 61 | /** 62 | * Verifies the provided {@link Authorization} header against the original {@link Challenge} 63 | * @param challenge the WWW-Authenticate challenge sent to the client in the previous response 64 | * @param requestContent the {@link RequestContent} containing the request header content 65 | * @param authorization the {@link Authorization} header to verify 66 | * @return a {@link net.adamcin.httpsig.api.VerifyResult} 67 | */ 68 | VerifyResult verifyWithResult(Challenge challenge, RequestContent requestContent, Authorization authorization); 69 | } 70 | -------------------------------------------------------------------------------- /http-helpers/src/main/java/net/adamcin/httpsig/http/apache3/Http3Util.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.http.apache3; 29 | 30 | import net.adamcin.httpsig.api.Constants; 31 | import net.adamcin.httpsig.api.KeyId; 32 | import net.adamcin.httpsig.api.Keychain; 33 | import net.adamcin.httpsig.api.Signer; 34 | import org.apache.commons.httpclient.HttpClient; 35 | import org.apache.commons.httpclient.auth.AuthPolicy; 36 | import org.apache.commons.httpclient.auth.CredentialsProvider; 37 | import org.apache.commons.httpclient.params.DefaultHttpParams; 38 | 39 | import java.util.ArrayList; 40 | import java.util.Collection; 41 | import java.util.List; 42 | 43 | public final class Http3Util { 44 | 45 | public static void enableAuth(HttpClient client, Keychain keychain, KeyId keyId) { 46 | Signer signer = new Signer(keychain, keyId); 47 | CredentialsProvider credProvider = 48 | (CredentialsProvider) client.getParams() 49 | .getParameter(CredentialsProvider.PROVIDER); 50 | 51 | CredentialsProvider newProvider; 52 | if (credProvider instanceof SignerCredentialsProvider) { 53 | newProvider = new SignerCredentialsProvider(signer, 54 | ((SignerCredentialsProvider) credProvider).getDelegatee()); 55 | } else { 56 | newProvider = new SignerCredentialsProvider(signer, credProvider); 57 | } 58 | 59 | client.getParams().setParameter(CredentialsProvider.PROVIDER, newProvider); 60 | AuthPolicy.registerAuthScheme(Constants.SCHEME, Http3SignatureAuthScheme.class); 61 | List schemes = new ArrayList(); 62 | schemes.add(Constants.SCHEME); 63 | 64 | Collection authSchemePriority = (Collection) DefaultHttpParams.getDefaultParams().getParameter(AuthPolicy.AUTH_SCHEME_PRIORITY); 65 | if (authSchemePriority != null) { 66 | schemes.addAll(authSchemePriority); 67 | } 68 | client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, schemes); 69 | } 70 | 71 | private Http3Util() { 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/site/site.xml: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 30 | 31 | org.apache.maven.skins 32 | maven-fluido-skin 33 | 1.5 34 | 35 | UA-37073514-1 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ${project.name} 45 | ${project.url} 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /test-common/src/main/resources/b2048/id_rsa.properties: -------------------------------------------------------------------------------- 1 | # 2 | # This is free and unencumbered software released into the public domain. 3 | # 4 | # Anyone is free to copy, modify, publish, use, compile, sell, or 5 | # distribute this software, either in source code form or as a compiled 6 | # binary, for any purpose, commercial or non-commercial, and by any 7 | # means. 8 | # 9 | # In jurisdictions that recognize copyright laws, the author or authors 10 | # of this software dedicate any and all copyright interest in the 11 | # software to the public domain. We make this dedication for the benefit 12 | # of the public at large and to the detriment of our heirs and 13 | # successors. We intend this dedication to be an overt act of 14 | # relinquishment in perpetuity of all present and future rights to this 15 | # software under copyright law. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | # OTHER DEALINGS IN THE SOFTWARE. 24 | # 25 | # For more information, please refer to 26 | # 27 | 28 | type=ssh-rsa 29 | n=24230984506923071981939437769066534985809649875417579437118871672088808918984242140840719373382849466315010530701437876386847579297807093301836199099895040023724638475230003200912927642906600192113435482947612799331174506469437147933417369569642953995177563315324874314107211022926843880098304080624650680201851614981574511525304667050117602675914804528336744047294816825496988401161943995520413420175102008960482154812668397638889359408257380135257519083439492793980222927541276207538121776773817128038867911511296593667885523631299358383638459076231112648828473394677852633677657846903509858083834877520977431994257 30 | e=65537 31 | d=12679884853821913630782809989626269394972945702083493092390431420331808014961999850773341332532230990849036210848922165657368169614390256874536100952605404544206119848452217217378104788340660292484097073221056516976099450682352670832911922873962877569382402824344516297699113508877063504096485015258897951958616082920747173874466467870228673028740520300245619840042244336423141330529052095580631876393364372463903559269061654006912278445908913734833052756509500115039608110577034966364536794930965140663052545191805782550741989565740794193635442758920401438608950647801584682870928351536555354614228342899178326220433 32 | p=158690641472101002239676873820999946363597464394463433952982565782375385746792828155459816593542873098331771908204988388830116647297982469727497610594461949450495091373975547605502861205484822756669970050882627804704840048509768973939258072464250901277329415227032185481379886747950704117168543699224777570613 33 | q=152693216702278311054233365940091742976852816466054123857986262159184720360989126599014799581211537723446561244848491079742578742603005204828642889863164419705386190362164617050780515527782300219230317776629869900854461971185727941021959070792190539441658672409780781734343818891490681146935092865827593466989 34 | pe=116326000686043063438917202423587567683195535147693941293242526248548085915767799219012848451567712384102974720266045854826855575519818969867078333011406480515605454700354903070265086213477827334989121125691629497319456501982968571601017700829380007450206485449774222541632530315063243305200024533537658715989 35 | qe=60057266077706151090910073299628375707071349772578499941823883907980294135300924917875467122463490972996658516692243382555265762059259123317636263057552058329580844850474042658619853651519666032181819450511743845985099504573821034464852510304260120774335651596913487202132850444267441108450888640042081218221 36 | u=8790455534483058834381407309944055028057446506577249331703747799916114454962839672974424724661370981142567850214265518079586622245026662315073282583597826588968159050337576267630844193130103731672919008745238500019576584057800473107306835837097338108708970191386262007435741631424465569834128599125579846023 -------------------------------------------------------------------------------- /test-common/src/main/resources/withpass/id_rsa.properties: -------------------------------------------------------------------------------- 1 | # 2 | # This is free and unencumbered software released into the public domain. 3 | # 4 | # Anyone is free to copy, modify, publish, use, compile, sell, or 5 | # distribute this software, either in source code form or as a compiled 6 | # binary, for any purpose, commercial or non-commercial, and by any 7 | # means. 8 | # 9 | # In jurisdictions that recognize copyright laws, the author or authors 10 | # of this software dedicate any and all copyright interest in the 11 | # software to the public domain. We make this dedication for the benefit 12 | # of the public at large and to the detriment of our heirs and 13 | # successors. We intend this dedication to be an overt act of 14 | # relinquishment in perpetuity of all present and future rights to this 15 | # software under copyright law. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | # OTHER DEALINGS IN THE SOFTWARE. 24 | # 25 | # For more information, please refer to 26 | # 27 | 28 | type=ssh-rsa 29 | n=30373819386151601618000267380169372298766224720335183271038184794270069217115483659208770115480455431888314892634104734829603788436875733930164097029221003850340848962331397827854012839967948437436246479849243842106418844202078218495539640585082054446040234933368454114071773785600734040459697134559479697642558629311171460155184142380716726648912130987245252108399688163334385100956163701799601626321096837761703452497607335411390705499736040486938499720429013786219805638399693327490339153240929905885465790019437853867801685678140583084580987574131109549066187247868600182759089426406731747404007226538060245942773 30 | e=65537 31 | d=24058241364956126157596378834926714924835661156790810742017366871699334621060847410615793470781244815437423532914786712620424075831335266312385648973661630985110601181540547495977872141274947028202626833223587406255156662687182512505965526996530348448875422973147328273516727607466531944401832220806301647994371473922824965218967657287718615075772864408430892648286041916942715421614244097788237180287065737179564872047234909768551381639753482342029559259883475952174176949518328923365422164251065981730408232804422349546822451429034575807723813809294189069921020332540019816913798894735748625128299462089586536056513 32 | p=176400244767545490396833544562679844293057122025230413006240910076938415028146983189202370870586023432287006813264642156761783749693891614531415210139145824885717484186397251683385797639195846404188570632007326684473791981150374657209792739090434712435331278595835312680225943245118622230483926636413975143389 33 | q=172186945807117408854283298392249921149102477523327195475852779925242089774429443774188504449288945372815732539290982957931717000966364394472366243771213299849999640620872214304359011958464723232659142845272416563984742101832454724601100717920403808400959811814177338946526011300762467399811840703703045726457 34 | pe=101880245734415129728406037738102061222462198846102146309706344314237696983847162071722827407762814485489044278634663934504024851757991539155417506431127586214646573598720148518666338502543631570638594793660212129545409467606433482613605520046874960715164322842531126237991244301249446420282391734667521753397 35 | qe=143956347325382258357018027763067544739637501693061075339318637070110999632582176225267200753550511846244405714219929783648849320489937560491476436649714193896290344521397536752741794455470941839935605150955433547062758277669161836372484406309333131969809268183200402147764670509656791030570370566814124562369 36 | u=121467151993328979876720815214714856987497000644779750043019415331858117113869047925957899224248018025704683690625897649384968302707573822976154379223490115719256551056785998332679149755038781583248287794583531783613465430964817085048321811976979448959143323457832071886764566772155586942124884455165392519577 37 | -------------------------------------------------------------------------------- /ssh-jce/src/main/java/net/adamcin/httpsig/ssh/jce/SSHRSASignature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.ssh.jce; 29 | 30 | import java.security.InvalidKeyException; 31 | import java.security.InvalidParameterException; 32 | import java.security.NoSuchAlgorithmException; 33 | import java.security.PrivateKey; 34 | import java.security.PublicKey; 35 | import java.security.Signature; 36 | import java.security.SignatureException; 37 | 38 | /** 39 | * The "ssh-rsa" key format has the following specific encoding: 40 | * 41 | * string "ssh-rsa" 42 | * mpint e 43 | * mpint n 44 | * 45 | * Here the 'e' and 'n' parameters form the signature key blob. 46 | * 47 | * Signing and verifying using this key format is performed according to the RSASSA-PKCS1-v1_5 scheme in [RFC3447] 48 | * using the SHA-1 hash. 49 | * 50 | * The resulting signature is encoded as follows: 51 | * 52 | * string "ssh-rsa" 53 | * string rsa_signature_blob 54 | * 55 | * The value for 'rsa_signature_blob' is encoded as a string containing {@code s} (which is an integer, without lengths 56 | * or padding, unsigned, and in network byte order). 57 | */ 58 | public final class SSHRSASignature extends Signature { 59 | 60 | private final Signature wrapped; 61 | 62 | public SSHRSASignature() throws NoSuchAlgorithmException { 63 | super("ssh-rsa"); 64 | this.wrapped = Signature.getInstance("SHA1withRSA"); 65 | } 66 | 67 | @Override 68 | protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { 69 | this.wrapped.initVerify(publicKey); 70 | } 71 | 72 | @Override 73 | protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException { 74 | this.wrapped.initSign(privateKey); 75 | } 76 | 77 | @Override 78 | protected void engineUpdate(byte b) throws SignatureException { 79 | this.wrapped.update(b); 80 | } 81 | 82 | @Override 83 | protected void engineUpdate(byte[] b, int off, int len) throws SignatureException { 84 | this.wrapped.update(b, off, len); 85 | } 86 | 87 | @Override 88 | protected byte[] engineSign() throws SignatureException { 89 | return this.wrapped.sign(); 90 | } 91 | 92 | @Override 93 | protected boolean engineVerify(byte[] sigBytes) throws SignatureException { 94 | final byte[] extracted = Magic.extractSignatureFromDER(sigBytes); 95 | return this.wrapped.verify(extracted); 96 | } 97 | 98 | @Override 99 | protected void engineSetParameter(String param, Object value) throws InvalidParameterException { 100 | this.wrapped.setParameter(param, value); 101 | } 102 | 103 | @Override 104 | protected Object engineGetParameter(String param) throws InvalidParameterException { 105 | return this.wrapped.getParameter(param); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /ssh-jce/src/main/java/net/adamcin/httpsig/ssh/jce/SSHDSSSignature.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.ssh.jce; 29 | 30 | import java.security.InvalidKeyException; 31 | import java.security.InvalidParameterException; 32 | import java.security.NoSuchAlgorithmException; 33 | import java.security.PrivateKey; 34 | import java.security.PublicKey; 35 | import java.security.Signature; 36 | import java.security.SignatureException; 37 | 38 | /** 39 | * The "ssh-dss" key format has the following specific encoding: 40 | * 41 | * string "ssh-dss" 42 | * mpint p 43 | * mpint q 44 | * mpint g 45 | * mpint y 46 | * 47 | * Here, the 'p', 'q', 'g', and 'y' parameters form the signature key blob. 48 | * 49 | * Signing and verifying using this key format is done according to the Digital Signature Standard [FIPS-186-2] 50 | * using the SHA-1 hash [FIPS-180-2]. 51 | * 52 | * The resulting signature is encoded as follows: 53 | * 54 | * string "ssh-dss" 55 | * string dss_signature_blob 56 | * 57 | * The value for 'dss_signature_blob' is encoded as a string containing r, followed by s (which are 160-bit 58 | * integers, without lengths or padding, unsigned, and in network byte order). 59 | */ 60 | public final class SSHDSSSignature extends Signature { 61 | 62 | private final Signature wrapped; 63 | 64 | public SSHDSSSignature() throws NoSuchAlgorithmException { 65 | super("ssh-dss"); 66 | this.wrapped = Signature.getInstance("SHA1withDSA"); 67 | } 68 | 69 | @Override 70 | protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { 71 | this.wrapped.initVerify(publicKey); 72 | } 73 | 74 | @Override 75 | protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException { 76 | this.wrapped.initSign(privateKey); 77 | } 78 | 79 | @Override 80 | protected void engineUpdate(byte b) throws SignatureException { 81 | this.wrapped.update(b); 82 | } 83 | 84 | @Override 85 | protected void engineUpdate(byte[] b, int off, int len) throws SignatureException { 86 | this.wrapped.update(b, off, len); 87 | } 88 | 89 | @Override 90 | protected byte[] engineSign() throws SignatureException { 91 | return Magic.dssPadSignature(this.wrapped.sign()); 92 | } 93 | 94 | @Override 95 | protected boolean engineVerify(byte[] sigBytes) throws SignatureException { 96 | final byte[] extracted = Magic.extractSignatureFromDER(sigBytes); 97 | return this.wrapped.verify(Magic.dssUnpadSignature(extracted)); 98 | } 99 | 100 | @Override 101 | protected void engineSetParameter(String param, Object value) throws InvalidParameterException { 102 | this.wrapped.setParameter(param, value); 103 | } 104 | 105 | @Override 106 | protected Object engineGetParameter(String param) throws InvalidParameterException { 107 | return this.wrapped.getParameter(param); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /http-helpers/src/main/java/net/adamcin/httpsig/http/ning/RotateAndReplayResponseFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.http.ning; 29 | 30 | import com.ning.http.client.FluentCaseInsensitiveStringsMap; 31 | import com.ning.http.client.Request; 32 | import com.ning.http.client.RequestBuilder; 33 | import com.ning.http.client.filter.FilterContext; 34 | import com.ning.http.client.filter.FilterException; 35 | import com.ning.http.client.filter.ResponseFilter; 36 | import net.adamcin.httpsig.api.Authorization; 37 | import net.adamcin.httpsig.api.Challenge; 38 | import net.adamcin.httpsig.api.Constants; 39 | import net.adamcin.httpsig.api.Signer; 40 | 41 | import java.util.List; 42 | 43 | /** 44 | * Implementation of {@link ResponseFilter} which calls 45 | * {@link Signer#rotateKeys(net.adamcin.httpsig.api.Challenge, net.adamcin.httpsig.api.Authorization)} so long as the 46 | * response is a 401 or no keys are left to try. 47 | */ 48 | public class RotateAndReplayResponseFilter implements ResponseFilter { 49 | 50 | private final Signer signer; 51 | 52 | public RotateAndReplayResponseFilter(Signer signer) { 53 | this.signer = signer; 54 | } 55 | 56 | public FilterContext filter(FilterContext ctx) throws FilterException { 57 | if (ctx.getResponseStatus().getStatusCode() == 401) { 58 | Challenge challenge = null; 59 | for (String header : ctx.getResponseHeaders().getHeaders().get(Constants.CHALLENGE)) { 60 | challenge = Challenge.parse(header); 61 | if (challenge != null) { 62 | break; 63 | } 64 | } 65 | 66 | if (challenge != null) { 67 | Authorization authorization = null; 68 | Request request = ctx.getRequest(); 69 | for (FluentCaseInsensitiveStringsMap.Entry> headersEntry : request.getHeaders()) { 70 | if (headersEntry.getKey().equalsIgnoreCase(Constants.AUTHORIZATION)) { 71 | for (String header : headersEntry.getValue()) { 72 | authorization = Authorization.parse(header); 73 | if (authorization != null) { 74 | break; 75 | } 76 | } 77 | } 78 | } 79 | 80 | 81 | boolean replay = signer.rotateKeys(challenge, authorization); 82 | if (!replay) { 83 | signer.rotateKeys(challenge); 84 | return ctx; 85 | } 86 | 87 | RequestBuilder builder = new RequestBuilder(request); 88 | AsyncUtil.calculateSignature(signer, request, builder); 89 | 90 | return new FilterContext.FilterContextBuilder(ctx) 91 | .replayRequest(replay) 92 | .request(builder.build()) 93 | .build(); 94 | } 95 | } 96 | 97 | return ctx; 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /hmac/src/test/java/net/adamcin/httpsig/hmac/HmacKeyTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.hmac; 29 | 30 | import net.adamcin.httpsig.api.Algorithm; 31 | import org.junit.Rule; 32 | import org.junit.Test; 33 | import org.junit.rules.ExpectedException; 34 | 35 | import static org.hamcrest.Matchers.hasItem; 36 | import static org.hamcrest.Matchers.is; 37 | import static org.junit.Assert.assertThat; 38 | 39 | public class HmacKeyTest { 40 | 41 | static final String UTF_8 = "UTF-8"; 42 | 43 | @Rule 44 | public ExpectedException expectedException = ExpectedException.none(); 45 | 46 | @Test 47 | public void shouldBeAbleToVerify() throws Exception { 48 | assertThat(new HmacKey("", "").canVerify(), is(true)); 49 | } 50 | 51 | @Test 52 | public void shouldBeAbleToSign() throws Exception { 53 | assertThat(new HmacKey("", "").canSign(), is(true)); 54 | } 55 | 56 | @Test 57 | public void shouldReturnSuppliedId() throws Exception { 58 | assertThat(new HmacKey("myId", "").getId(), is("myId")); 59 | } 60 | 61 | @Test 62 | public void shouldSupportHmacSha256() throws Exception { 63 | assertThat(new HmacKey("", "").getAlgorithms(), hasItem(Algorithm.HMAC_SHA256)); 64 | } 65 | 66 | @Test 67 | public void shouldSupportHmacSha512() throws Exception { 68 | assertThat(new HmacKey("", "").getAlgorithms(), hasItem(Algorithm.HMAC_SHA512)); 69 | } 70 | 71 | @Test 72 | public void shouldCreateVerifiableSignature() throws Exception { 73 | HmacKey key = new HmacKey("key1", "abcd"); 74 | 75 | byte[] sig = key.sign(Algorithm.HMAC_SHA256, "hello".getBytes(UTF_8)); 76 | 77 | assertThat(key.verify(Algorithm.HMAC_SHA256, "hello".getBytes(UTF_8), sig), is(true)); 78 | } 79 | 80 | @Test 81 | public void shouldFailVerificationIfSigningAndVerifyingAlgorithmsAreDifferent() throws Exception { 82 | HmacKey key = new HmacKey("key1", "abcd"); 83 | 84 | byte[] sig = key.sign(Algorithm.HMAC_SHA256, "hello".getBytes(UTF_8)); 85 | 86 | assertThat(key.verify(Algorithm.HMAC_SHA512, "hello".getBytes(UTF_8), sig), is(false)); 87 | } 88 | 89 | @Test 90 | public void shouldFailVerificationIfSignatureDoesNotMatch() throws Exception { 91 | HmacKey key = new HmacKey("key1", "abcd"); 92 | 93 | byte[] sig = key.sign(Algorithm.HMAC_SHA256, "hello1".getBytes(UTF_8)); 94 | 95 | assertThat(key.verify(Algorithm.HMAC_SHA512, "hello".getBytes(UTF_8), sig), is(false)); 96 | } 97 | 98 | @Test 99 | public void signingShouldThrowIfUnsupportAlgorithm() throws Exception { 100 | expectedException.expect(IllegalArgumentException.class); 101 | expectedException.expectMessage("Unsupported algorithm: hmac-sha1"); 102 | 103 | HmacKey key = new HmacKey("key1", "abcd"); 104 | 105 | key.sign(Algorithm.HMAC_SHA1, "hello".getBytes(UTF_8)); 106 | } 107 | 108 | @Test 109 | public void verifyingReturnFalseIfUnsupportedAlgorithm() throws Exception { 110 | HmacKey key = new HmacKey("key1", "abcd"); 111 | 112 | byte[] sig = key.sign(Algorithm.HMAC_SHA256, "hello".getBytes(UTF_8)); 113 | 114 | key.verify(Algorithm.HMAC_SHA1, "hello".getBytes(UTF_8), sig); 115 | } 116 | } -------------------------------------------------------------------------------- /api/src/test/java/net/adamcin/httpsig/api/DefaultVerifierTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | 31 | import static org.junit.Assert.assertFalse; 32 | import static org.junit.Assert.assertTrue; 33 | 34 | import java.util.Arrays; 35 | import java.util.List; 36 | 37 | import net.adamcin.commons.testing.junit.TestBody; 38 | import org.junit.Test; 39 | 40 | public class DefaultVerifierTest { 41 | 42 | @Test 43 | public void testVerify() { 44 | TestBody.test(new TestBody() { 45 | @Override protected void execute() throws Exception { 46 | String fingerprint = "fingerprint"; 47 | 48 | Keychain identities = new MockKeychain(fingerprint); 49 | DefaultVerifier v = new DefaultVerifier(identities); 50 | RequestContent requestContent = new RequestContent.Builder().addDateNow().build(); 51 | Challenge c = new Challenge(DefaultVerifierTest.class.getName(), Constants.DEFAULT_HEADERS, Arrays.asList( Algorithm.SSH_RSA )); 52 | 53 | byte[] content = requestContent.getContent(Constants.DEFAULT_HEADERS, Constants.CHARSET); 54 | Authorization a = new Authorization(fingerprint, MockKey.mockSignBase64(content), Constants.DEFAULT_HEADERS, Algorithm.SSH_RSA); 55 | 56 | assertTrue("default verifier should verify mock signature ", v.verify(c, requestContent, a)); 57 | } 58 | }); 59 | } 60 | 61 | 62 | @Test 63 | public void testStrictVerify() { 64 | TestBody.test(new TestBody() { 65 | @Override protected void execute() throws Exception { 66 | String fingerprint = "fingerprint"; 67 | 68 | Keychain identities = new MockKeychain(fingerprint); 69 | DefaultVerifier v = new DefaultVerifier(identities); 70 | DefaultVerifier strictV = new DefaultVerifier(identities, true); 71 | RequestContent requestContent = new RequestContent.Builder().setRequestTarget("get", "index.html").addDateNow().build(); 72 | List headers = Arrays.asList(Constants.HEADER_REQUEST_TARGET, Constants.HEADER_DATE); 73 | Challenge c = new Challenge(DefaultVerifierTest.class.getName(), 74 | headers, 75 | Arrays.asList( Algorithm.SSH_RSA )); 76 | 77 | byte[] content = requestContent.getContent(headers, Constants.CHARSET); 78 | byte[] strictContent = requestContent.getBytesToSign(headers, Constants.CHARSET); 79 | Authorization authz = new Authorization(fingerprint, MockKey.mockSignBase64(content), headers, Algorithm.SSH_RSA); 80 | Authorization strictAuthz = new Authorization(fingerprint, MockKey.mockSignBase64(strictContent), headers, Algorithm.SSH_RSA); 81 | 82 | assertTrue("default verifier should verify default mock signature ", v.verify(c, requestContent, authz)); 83 | assertTrue("default verifier should verify strict mock signature ", v.verify(c, requestContent, strictAuthz)); 84 | assertTrue("strict verifier should verify strict mock signature ", strictV.verify(c, requestContent, strictAuthz)); 85 | assertFalse("strict verifier should not verify default mock signature ", strictV.verify(c, requestContent, authz)); 86 | } 87 | }); 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /ssh-jce/src/test/java/net/adamcin/httpsig/ssh/jce/KeyFormatTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.ssh.jce; 29 | 30 | import com.jcraft.jsch.HASH; 31 | import com.jcraft.jsch.jce.MD5; 32 | import net.adamcin.commons.testing.junit.FailUtil; 33 | import net.adamcin.httpsig.api.Base64; 34 | import net.adamcin.httpsig.testutil.KeyTestUtil; 35 | import org.junit.Test; 36 | 37 | import java.io.File; 38 | import java.security.KeyPair; 39 | import java.util.List; 40 | 41 | import static org.junit.Assert.*; 42 | 43 | public class KeyFormatTest { 44 | 45 | @Test 46 | public void testFingerprint() { 47 | KeyPair rsaKeyPair = KeyTestUtil.getKeyPairFromProperties("b1024", "id_rsa"); 48 | 49 | File rsaPubKeyFile = KeyTestUtil.getPublicKeyAsFile("b1024", "id_rsa"); 50 | 51 | try { 52 | List authorizedKeys = AuthorizedKeys.parseAuthorizedKeys(rsaPubKeyFile); 53 | assertEquals("rsaPubKeyFile should only contain one pubkey", 1, authorizedKeys.size()); 54 | 55 | AuthorizedKeys.AuthorizedKey authorizedKey = authorizedKeys.get(0); 56 | byte[] keyBlob = Base64.fromBase64String(authorizedKey.getEncodedKey()); 57 | 58 | assertEquals( 59 | "KeyFormat.SSH_RSA.getFingerprint() should return same output as JSch fingerprint algorithm", 60 | getJschFingerprint(keyBlob), KeyFormat.SSH_RSA.getFingerprint(rsaKeyPair.getPublic()) 61 | ); 62 | } catch (Exception e) { 63 | FailUtil.sprintFail(e); 64 | } 65 | 66 | KeyPair dsaKeyPair = KeyTestUtil.getKeyPairFromProperties("b1024", "id_dsa"); 67 | 68 | File dsaPubKeyFile = KeyTestUtil.getPublicKeyAsFile("b1024", "id_dsa"); 69 | 70 | try { 71 | List authorizedKeys = AuthorizedKeys.parseAuthorizedKeys(dsaPubKeyFile); 72 | assertEquals("dsaPubKeyFile should only contain one pubkey", 1, authorizedKeys.size()); 73 | 74 | AuthorizedKeys.AuthorizedKey authorizedKey = authorizedKeys.get(0); 75 | byte[] keyBlob = Base64.fromBase64String(authorizedKey.getEncodedKey()); 76 | 77 | assertEquals("KeyFormat.SSH_DSS.getFingerprint() should return same output as JSch fingerprint algorithm", 78 | getJschFingerprint(keyBlob), KeyFormat.SSH_DSS.getFingerprint(dsaKeyPair.getPublic())); 79 | } catch (Exception e) { 80 | FailUtil.sprintFail(e); 81 | } 82 | 83 | } 84 | 85 | public static String getJschFingerprint(byte[] keyBlob) throws Exception { 86 | final String[] fingerPrintChars = { 87 | "0","1","2","3","4","5","6","7","8","9", "a","b","c","d","e","f" 88 | }; 89 | HASH hash = new MD5(); 90 | hash.init(); 91 | hash.update(keyBlob, 0, keyBlob.length); 92 | byte[] foo = hash.digest(); 93 | StringBuffer sb = new StringBuffer(); 94 | int bar; 95 | for(int i = 0; i < foo.length; i++){ 96 | bar = foo[i]&0xff; 97 | sb.append(fingerPrintChars[(bar>>>4)&0xf]); 98 | sb.append(fingerPrintChars[(bar)&0xf]); 99 | if(i + 1 < foo.length) { 100 | sb.append(":"); 101 | } 102 | } 103 | return sb.toString(); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /http-helpers/src/main/java/net/adamcin/httpsig/http/apache4/Http4SignatureAuthScheme.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.http.apache4; 29 | 30 | import net.adamcin.httpsig.api.Authorization; 31 | import net.adamcin.httpsig.api.Challenge; 32 | import net.adamcin.httpsig.api.Constants; 33 | import net.adamcin.httpsig.api.RequestContent; 34 | import net.adamcin.httpsig.api.Signer; 35 | import org.apache.http.Header; 36 | import org.apache.http.HttpRequest; 37 | import org.apache.http.auth.AuthenticationException; 38 | import org.apache.http.auth.Credentials; 39 | import org.apache.http.auth.MalformedChallengeException; 40 | import org.apache.http.impl.auth.RFC2617Scheme; 41 | import org.apache.http.message.BasicHeader; 42 | import org.apache.http.util.CharArrayBuffer; 43 | 44 | public final class Http4SignatureAuthScheme extends RFC2617Scheme { 45 | 46 | private boolean rotate = false; 47 | private Authorization lastAuthz = null; 48 | 49 | public String getSchemeName() { 50 | return Constants.SCHEME; 51 | } 52 | 53 | public boolean isConnectionBased() { 54 | return false; 55 | } 56 | 57 | public boolean isComplete() { 58 | return true; 59 | } 60 | 61 | @Override 62 | protected void parseChallenge(CharArrayBuffer buffer, int pos, int len) throws MalformedChallengeException { 63 | super.parseChallenge(buffer, pos, len); 64 | this.rotate = true; 65 | } 66 | 67 | public Header authenticate(Credentials credentials, HttpRequest request) 68 | throws AuthenticationException { 69 | 70 | if (credentials instanceof SignerCredentials) { 71 | Signer signer = ((SignerCredentials) credentials).getSigner(); 72 | String headers = this.getParameter(Constants.HEADERS); 73 | String algorithms = this.getParameter(Constants.ALGORITHMS); 74 | 75 | Challenge challenge = new Challenge(this.getRealm(), Constants.parseTokens(headers), Challenge.parseAlgorithms(algorithms)); 76 | 77 | if (this.rotate) { 78 | this.rotate = false; 79 | if (!signer.rotateKeys(challenge, this.lastAuthz)) { 80 | signer.rotateKeys(challenge); 81 | return null; 82 | } 83 | } 84 | 85 | RequestContent.Builder sigBuilder = new RequestContent.Builder(); 86 | sigBuilder.setRequestTarget(request.getRequestLine().getMethod(), 87 | request.getRequestLine().getUri()); 88 | 89 | for (Header header : request.getAllHeaders()) { 90 | if (header.getName().toLowerCase().equals("connection")) { 91 | sigBuilder.addHeader("connection", header.getValue().toLowerCase()); 92 | } else { 93 | sigBuilder.addHeader(header.getName(), header.getValue()); 94 | } 95 | } 96 | 97 | if (sigBuilder.build().getDate() == null) { 98 | sigBuilder.addDateNow(); 99 | request.addHeader(Constants.HEADER_DATE, sigBuilder.build().getDate()); 100 | } 101 | 102 | Authorization authorization = signer.sign(sigBuilder.build()); 103 | this.lastAuthz = authorization; 104 | if (authorization != null) { 105 | return new BasicHeader(Constants.AUTHORIZATION, authorization.getHeaderValue()); 106 | } 107 | } 108 | 109 | return null; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /http-helpers/src/main/java/net/adamcin/httpsig/http/apache3/Http3SignatureAuthScheme.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.http.apache3; 29 | 30 | import net.adamcin.httpsig.api.Authorization; 31 | import net.adamcin.httpsig.api.Challenge; 32 | import net.adamcin.httpsig.api.Constants; 33 | import net.adamcin.httpsig.api.RequestContent; 34 | import net.adamcin.httpsig.api.Signer; 35 | import org.apache.commons.httpclient.Credentials; 36 | import org.apache.commons.httpclient.Header; 37 | import org.apache.commons.httpclient.HttpMethod; 38 | import org.apache.commons.httpclient.auth.AuthenticationException; 39 | import org.apache.commons.httpclient.auth.MalformedChallengeException; 40 | import org.apache.commons.httpclient.auth.RFC2617Scheme; 41 | 42 | public final class Http3SignatureAuthScheme extends RFC2617Scheme { 43 | 44 | private boolean rotate = false; 45 | private Authorization lastAuthz = null; 46 | 47 | public String getSchemeName() { 48 | return Constants.SCHEME; 49 | } 50 | 51 | public boolean isConnectionBased() { 52 | return false; 53 | } 54 | 55 | public boolean isComplete() { 56 | return true; 57 | } 58 | 59 | @Override 60 | public void processChallenge(String challenge) throws MalformedChallengeException { 61 | super.processChallenge(challenge); 62 | this.rotate = true; 63 | } 64 | 65 | public String authenticate(Credentials credentials, String method, String uri) throws AuthenticationException { 66 | throw new AuthenticationException("Signature authentication requires access to all request headers"); 67 | } 68 | 69 | public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException { 70 | if (credentials instanceof SignerCredentials) { 71 | SignerCredentials creds = (SignerCredentials) credentials; 72 | String headers = this.getParameter(Constants.HEADERS); 73 | String algorithms = this.getParameter(Constants.ALGORITHMS); 74 | 75 | Challenge challenge = new Challenge(this.getRealm(), Constants.parseTokens(headers), Challenge.parseAlgorithms(algorithms)); 76 | 77 | Signer signer = creds.getSigner(); 78 | if (signer != null) { 79 | 80 | if (this.rotate) { 81 | this.rotate = false; 82 | if (!signer.rotateKeys(challenge, this.lastAuthz)) { 83 | signer.rotateKeys(challenge); 84 | return null; 85 | } 86 | } 87 | 88 | RequestContent.Builder sigBuilder = new RequestContent.Builder(); 89 | 90 | sigBuilder.setRequestTarget(method.getName(), method.getPath() + (method.getQueryString() != null ? "?" + method.getQueryString() : "")); 91 | 92 | for (Header header : method.getRequestHeaders()) { 93 | sigBuilder.addHeader(header.getName(), header.getValue()); 94 | } 95 | 96 | if (sigBuilder.build().getDate() == null) { 97 | sigBuilder.addDateNow(); 98 | method.addRequestHeader(Constants.HEADER_DATE, sigBuilder.build().getDate()); 99 | } 100 | 101 | Authorization authorization = creds.getSigner().sign(sigBuilder.build()); 102 | this.lastAuthz = authorization; 103 | if (authorization != null) { 104 | return authorization.getHeaderValue(); 105 | } 106 | } 107 | } 108 | 109 | return null; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /http-helpers/src/test/java/net/adamcin/httpsig/http/apache3/Http3UtilTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.http.apache3; 29 | 30 | import net.adamcin.commons.testing.junit.TestBody; 31 | import net.adamcin.httpsig.api.Constants; 32 | import net.adamcin.httpsig.api.DefaultKeychain; 33 | import net.adamcin.httpsig.http.HttpServerTestBody; 34 | import net.adamcin.httpsig.ssh.jce.SSHKey; 35 | import net.adamcin.httpsig.ssh.jce.KeyFormat; 36 | import net.adamcin.httpsig.testutil.KeyTestUtil; 37 | import org.apache.commons.httpclient.HttpClient; 38 | import org.apache.commons.httpclient.HttpMethod; 39 | import org.apache.commons.httpclient.methods.GetMethod; 40 | import org.junit.Test; 41 | import org.slf4j.Logger; 42 | import org.slf4j.LoggerFactory; 43 | 44 | import java.security.KeyPair; 45 | import java.util.Arrays; 46 | import java.util.List; 47 | 48 | import static org.junit.Assert.*; 49 | 50 | public class Http3UtilTest { 51 | private static final Logger LOGGER = LoggerFactory.getLogger(Http3UtilTest.class); 52 | 53 | private static final String TEST_URL = "/index.html?path=/may/get/url/encoded&foo=bar"; 54 | 55 | @Test 56 | public void testLogin() { 57 | TestBody.test(new HttpServerTestBody() { 58 | 59 | @Override protected void execute() throws Exception { 60 | List headers = Arrays.asList( 61 | Constants.HEADER_REQUEST_TARGET, 62 | Constants.HEADER_DATE); 63 | setServlet(new AdminServlet(headers)); 64 | 65 | KeyPair keyPair = KeyTestUtil.getKeyPairFromProperties("b2048", "id_rsa"); 66 | 67 | DefaultKeychain provider = new DefaultKeychain(); 68 | provider.add(new SSHKey(KeyFormat.SSH_RSA, keyPair)); 69 | 70 | HttpClient client = new HttpClient(); 71 | 72 | Http3Util.enableAuth(client, provider, getKeyId()); 73 | HttpMethod request = new GetMethod(getAbsoluteUrl(TEST_URL)); 74 | try { 75 | int status = client.executeMethod(request); 76 | assertEquals("should return 200", 200, status); 77 | } finally { 78 | request.releaseConnection(); 79 | } 80 | } 81 | }); 82 | } 83 | 84 | @Test 85 | public void testAllHeaders() { 86 | TestBody.test(new HttpServerTestBody() { 87 | @Override protected void execute() throws Exception { 88 | List headers = Arrays.asList( 89 | Constants.HEADER_REQUEST_TARGET, 90 | Constants.HEADER_DATE, 91 | "x-test" 92 | ); 93 | 94 | setServlet(new AdminServlet(headers)); 95 | 96 | KeyPair keyPair = KeyTestUtil.getKeyPairFromProperties("b2048", "id_rsa"); 97 | 98 | DefaultKeychain provider = new DefaultKeychain(); 99 | provider.add(new SSHKey(KeyFormat.SSH_RSA, keyPair)); 100 | 101 | HttpClient client = new HttpClient(); 102 | 103 | Http3Util.enableAuth(client, provider, getKeyId()); 104 | HttpMethod request = new GetMethod(getAbsoluteUrl(TEST_URL)); 105 | request.addRequestHeader("x-test", "foo"); 106 | try { 107 | int status = client.executeMethod(request); 108 | assertEquals("should return 200", 200, status); 109 | } finally { 110 | request.releaseConnection(); 111 | } 112 | } 113 | }); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /api/src/main/java/net/adamcin/httpsig/api/Authorization.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | import java.io.Serializable; 31 | import java.util.ArrayList; 32 | import java.util.LinkedHashMap; 33 | import java.util.List; 34 | import java.util.Map; 35 | 36 | /** 37 | * Representation of the "Authorization: Signature..." header sent by the client in response to a {@link Challenge} 38 | */ 39 | public final class Authorization implements Serializable { 40 | 41 | private static final long serialVersionUID = -5642537789425001043L; 42 | 43 | private final String keyId; 44 | private final String signature; 45 | private final List headers; 46 | private final Algorithm algorithm; 47 | 48 | /** 49 | * Construct an {@link Authorization} instance 50 | * @param keyId the key identifier 51 | * @param signature the Base64-encoded Signature 52 | * @param headers the list of signed headers 53 | * @param algorithm the signing algorithm used 54 | */ 55 | public Authorization(final String keyId, final String signature, final List headers, final Algorithm algorithm) { 56 | this.keyId = keyId; 57 | this.signature = signature; 58 | this.headers = headers != null ? Constants.filterHeaders(new ArrayList(headers)) : Constants.DEFAULT_HEADERS; 59 | this.algorithm = algorithm; 60 | } 61 | 62 | public String getKeyId() { 63 | return keyId; 64 | } 65 | 66 | /** 67 | * @return the signature as a Base64-encoded string 68 | */ 69 | public String getSignature() { 70 | return signature; 71 | } 72 | 73 | /** 74 | * @return the signature as an unencoded byte array for verification using a {@link Verifier} 75 | */ 76 | public byte[] getSignatureBytes() { 77 | return Base64.fromBase64String(this.signature); 78 | } 79 | 80 | public List getHeaders() { 81 | return headers; 82 | } 83 | 84 | public Algorithm getAlgorithm() { 85 | return algorithm; 86 | } 87 | 88 | /** 89 | * @return the constructed {@link Authorization} header value 90 | */ 91 | public String getHeaderValue() { 92 | Map params = new LinkedHashMap(); 93 | params.put(Constants.KEY_ID, keyId); 94 | params.put(Constants.SIGNATURE, signature); 95 | params.put(Constants.HEADERS, Constants.constructTokensString(getHeaders())); 96 | params.put(Constants.ALGORITHM, algorithm.getName()); 97 | return Constants.constructRFC2617(params); 98 | } 99 | 100 | @Override 101 | public String toString() { 102 | return getHeaderValue(); 103 | } 104 | 105 | /** 106 | * Parse an Authorization header value to construct an {@link Authorization} instance 107 | * @param header the Authorization header value 108 | * @return the {@link Authorization} instance 109 | */ 110 | public static Authorization parse(String header) { 111 | if (header != null && header.toLowerCase().startsWith(Constants.SCHEME.toLowerCase())) { 112 | Map params = Constants.parseRFC2617(header); 113 | 114 | if (params.containsKey(Constants.KEY_ID) 115 | && params.containsKey(Constants.SIGNATURE) 116 | && params.containsKey(Constants.ALGORITHM)) { 117 | 118 | String keyId = params.get(Constants.KEY_ID); 119 | String signature = params.get(Constants.SIGNATURE); 120 | String algorithm = params.get(Constants.ALGORITHM); 121 | 122 | // headers are optional. use default headers if undefined 123 | String headers = params.get(Constants.HEADERS); 124 | 125 | return new Authorization(keyId, signature, headers != null ? Constants.parseTokens(headers) : Constants.DEFAULT_HEADERS, Algorithm.forName(algorithm)); 126 | } 127 | } 128 | 129 | return null; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /http-helpers/src/test/java/net/adamcin/httpsig/http/apache4/Http4UtilTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.http.apache4; 29 | 30 | import net.adamcin.commons.testing.junit.TestBody; 31 | import net.adamcin.httpsig.api.Constants; 32 | import net.adamcin.httpsig.api.DefaultKeychain; 33 | import net.adamcin.httpsig.http.HttpServerTestBody; 34 | import net.adamcin.httpsig.ssh.jce.SSHKey; 35 | import net.adamcin.httpsig.ssh.jce.KeyFormat; 36 | import net.adamcin.httpsig.testutil.KeyTestUtil; 37 | import org.apache.commons.io.output.NullOutputStream; 38 | import org.apache.http.HttpResponse; 39 | import org.apache.http.client.methods.HttpGet; 40 | import org.apache.http.client.methods.HttpUriRequest; 41 | import org.apache.http.impl.client.DefaultHttpClient; 42 | import org.junit.Test; 43 | import org.slf4j.Logger; 44 | import org.slf4j.LoggerFactory; 45 | 46 | import java.security.KeyPair; 47 | import java.util.Arrays; 48 | import java.util.List; 49 | 50 | import static org.junit.Assert.*; 51 | 52 | public class Http4UtilTest { 53 | private static final Logger LOGGER = LoggerFactory.getLogger(Http4UtilTest.class); 54 | 55 | private static final String TEST_URL = "/index.html?path=/may/get/url/encoded&foo=bar"; 56 | 57 | @Test 58 | public void testLogin() { 59 | TestBody.test(new HttpServerTestBody() { 60 | 61 | @Override protected void execute() throws Exception { 62 | 63 | List headers = Arrays.asList( 64 | Constants.HEADER_REQUEST_TARGET, 65 | Constants.HEADER_DATE); 66 | 67 | setServlet(new AdminServlet(headers)); 68 | 69 | KeyPair keyPair = KeyTestUtil.getKeyPairFromProperties("b2048", "id_rsa"); 70 | 71 | DefaultKeychain provider = new DefaultKeychain(); 72 | provider.add(new SSHKey(KeyFormat.SSH_RSA, keyPair)); 73 | 74 | DefaultHttpClient client = new DefaultHttpClient(); 75 | 76 | Http4Util.enableAuth(client, provider, getKeyId()); 77 | HttpUriRequest request = new HttpGet(getAbsoluteUrl(TEST_URL)); 78 | HttpResponse response = client.execute(request); 79 | 80 | assertEquals("should return 200", 200, response.getStatusLine().getStatusCode()); 81 | 82 | } 83 | }); 84 | } 85 | 86 | @Test 87 | public void testAllHeaders() { 88 | TestBody.test(new HttpServerTestBody() { 89 | @Override protected void execute() throws Exception { 90 | 91 | List headers = Arrays.asList( 92 | Constants.HEADER_REQUEST_TARGET, 93 | Constants.HEADER_DATE, 94 | "x-test" 95 | ); 96 | 97 | setServlet(new AdminServlet(headers)); 98 | 99 | KeyPair keyPair = KeyTestUtil.getKeyPairFromProperties("b2048", "id_rsa"); 100 | 101 | DefaultKeychain provider = new DefaultKeychain(); 102 | provider.add(new SSHKey(KeyFormat.SSH_RSA, keyPair)); 103 | 104 | DefaultHttpClient client = new DefaultHttpClient(); 105 | 106 | Http4Util.enableAuth(client, provider, getKeyId()); 107 | 108 | HttpUriRequest badRequest = new HttpGet(getAbsoluteUrl(TEST_URL)); 109 | HttpResponse badResponse = client.execute(badRequest); 110 | 111 | badResponse.getEntity().writeTo(new NullOutputStream()); 112 | 113 | assertEquals("should return 401", 401, badResponse.getStatusLine().getStatusCode()); 114 | 115 | HttpUriRequest goodRequest = new HttpGet(getAbsoluteUrl(TEST_URL)); 116 | goodRequest.addHeader("x-test", "foo"); 117 | HttpResponse goodResponse = client.execute(goodRequest); 118 | 119 | goodResponse.getEntity().writeTo(new NullOutputStream()); 120 | assertEquals("should return 200", 200, goodResponse.getStatusLine().getStatusCode()); 121 | } 122 | }); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /ssh-jce/src/main/java/net/adamcin/httpsig/ssh/jce/FingerprintGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.ssh.jce; 29 | 30 | import org.slf4j.Logger; 31 | import org.slf4j.LoggerFactory; 32 | 33 | import java.io.ByteArrayOutputStream; 34 | import java.io.DataOutputStream; 35 | import java.io.IOException; 36 | import java.security.PublicKey; 37 | import java.security.interfaces.DSAParams; 38 | import java.security.interfaces.DSAPublicKey; 39 | import java.security.interfaces.RSAPublicKey; 40 | 41 | public abstract class FingerprintGenerator { 42 | private static final Logger LOGGER = LoggerFactory.getLogger(FingerprintGenerator.class); 43 | 44 | abstract String getFingerprint(PublicKey publicKey); 45 | 46 | public static final FingerprintGenerator NOP = new FingerprintGenerator() { 47 | @Override String getFingerprint(PublicKey publicKey) { return ""; } 48 | }; 49 | 50 | public static final FingerprintGenerator DSA = new FingerprintGenerator() { 51 | public String getFingerprint(PublicKey publicKey) { 52 | ByteArrayOutputStream byteOs = new ByteArrayOutputStream(); 53 | try { 54 | if (publicKey instanceof DSAPublicKey) { 55 | DSAPublicKey dsaPublicKey = (DSAPublicKey) publicKey; 56 | DSAParams dsaParams = dsaPublicKey.getParams(); 57 | 58 | DataOutputStream dos = new DataOutputStream(byteOs); 59 | dos.writeInt(KeyFormat.SSH_DSS.getIdentifier().getBytes().length); 60 | dos.write(KeyFormat.SSH_DSS.getIdentifier().getBytes()); 61 | dos.writeInt(dsaParams.getP().toByteArray().length); 62 | dos.write(dsaParams.getP().toByteArray()); 63 | dos.writeInt(dsaParams.getQ().toByteArray().length); 64 | dos.write(dsaParams.getQ().toByteArray()); 65 | dos.writeInt(dsaParams.getG().toByteArray().length); 66 | dos.write(dsaParams.getG().toByteArray()); 67 | dos.writeInt(dsaPublicKey.getY().toByteArray().length); 68 | dos.write(dsaPublicKey.getY().toByteArray()); 69 | } else { 70 | throw new IllegalArgumentException("Not a DSA public key: " + publicKey); 71 | } 72 | return Magic.getFingerprint(byteOs.toByteArray()); 73 | } catch (IOException e) { 74 | LOGGER.error("[getFingerprint] failed to generate DSA fingerprint", e); 75 | } finally { 76 | try { 77 | byteOs.close(); 78 | } catch (IOException ignored) { 79 | } 80 | } 81 | 82 | return null; 83 | } 84 | }; 85 | 86 | public static final FingerprintGenerator RSA = new FingerprintGenerator() { 87 | public String getFingerprint(PublicKey publicKey) { 88 | ByteArrayOutputStream byteOs = new ByteArrayOutputStream(); 89 | try { 90 | if (publicKey instanceof RSAPublicKey) { 91 | RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; 92 | DataOutputStream dos = new DataOutputStream(byteOs); 93 | dos.writeInt(KeyFormat.SSH_RSA.getIdentifier().getBytes().length); 94 | dos.write(KeyFormat.SSH_RSA.getIdentifier().getBytes()); 95 | dos.writeInt(rsaPublicKey.getPublicExponent().toByteArray().length); 96 | dos.write(rsaPublicKey.getPublicExponent().toByteArray()); 97 | dos.writeInt(rsaPublicKey.getModulus().toByteArray().length); 98 | dos.write(rsaPublicKey.getModulus().toByteArray()); 99 | } else { 100 | throw new IllegalArgumentException("Not an RSA public key: " + publicKey); 101 | } 102 | return Magic.getFingerprint(byteOs.toByteArray()); 103 | } catch (IOException e) { 104 | LOGGER.error("[getFingerprint] failed to generate RSA fingerprint", e); 105 | } finally { 106 | try { 107 | byteOs.close(); 108 | } catch (IOException ignored) { 109 | } 110 | } 111 | 112 | return null; 113 | } 114 | }; 115 | } 116 | -------------------------------------------------------------------------------- /ssh-jce/src/main/java/net/adamcin/httpsig/ssh/jce/KeyFormat.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.ssh.jce; 29 | 30 | import net.adamcin.httpsig.api.Algorithm; 31 | import org.slf4j.Logger; 32 | import org.slf4j.LoggerFactory; 33 | 34 | import java.security.KeyFactory; 35 | import java.security.NoSuchAlgorithmException; 36 | import java.security.PublicKey; 37 | import java.security.Signature; 38 | import java.util.Arrays; 39 | import java.util.Collections; 40 | import java.util.List; 41 | 42 | /** 43 | * 44 | */ 45 | public enum KeyFormat { 46 | 47 | SSH_DSS( 48 | "ssh-dss", "DSA", FingerprintGenerator.DSA, Algorithm.SSH_DSS, 49 | Arrays.asList(Algorithm.SSH_DSS, Algorithm.DSA_SHA1) 50 | ), 51 | SSH_RSA( 52 | "ssh-rsa", "RSA", FingerprintGenerator.RSA, Algorithm.SSH_RSA, 53 | Arrays.asList(Algorithm.SSH_RSA, Algorithm.RSA_SHA1, Algorithm.RSA_SHA256, Algorithm.RSA_SHA512) 54 | ), 55 | UNKOWN("_unknown_", "_unknown_", FingerprintGenerator.NOP, null, Collections.emptyList()); 56 | 57 | private static final Logger LOGGER = LoggerFactory.getLogger(KeyFormat.class); 58 | 59 | private final String identifier; 60 | private final String keyAlgorithm; 61 | private final Algorithm defaultSignature; 62 | private final List signatureAlgorithms; 63 | private final FingerprintGenerator fingerprintGenerator; 64 | 65 | private KeyFormat(String identifier, String keyAlgorithm, FingerprintGenerator fingerprintGenerator, 66 | Algorithm defaultSignature, List signatureAlgorithms) { 67 | this.identifier = identifier; 68 | this.keyAlgorithm = keyAlgorithm; 69 | this.fingerprintGenerator = fingerprintGenerator; 70 | this.defaultSignature = defaultSignature; 71 | this.signatureAlgorithms = signatureAlgorithms; 72 | } 73 | 74 | public String getIdentifier() { 75 | return identifier; 76 | } 77 | 78 | public String getKeyAlgorithm() { 79 | return keyAlgorithm; 80 | } 81 | 82 | public KeyFactory getKeyFactory() { 83 | try { 84 | return KeyFactory.getInstance(getKeyAlgorithm()); 85 | } catch (NoSuchAlgorithmException e) { 86 | // should not happen in standard JVM 87 | e.printStackTrace(System.err); 88 | } 89 | 90 | return null; 91 | } 92 | 93 | public List getSignatureAlgorithms() { 94 | return signatureAlgorithms; 95 | } 96 | 97 | public String getFingerprint(PublicKey publicKey) { 98 | return fingerprintGenerator.getFingerprint(publicKey); 99 | } 100 | 101 | public Signature getSignatureInstance(Algorithm algorithm) { 102 | return getSignatureInstanceInternal(algorithm != null ? algorithm : defaultSignature); 103 | } 104 | 105 | private static Signature getSignatureInstanceInternal(Algorithm algorithm) { 106 | if (algorithm != null) { 107 | try { 108 | switch (algorithm) { 109 | case SSH_DSS: 110 | return new SSHDSSSignature(); 111 | case SSH_RSA: 112 | return new SSHRSASignature(); 113 | case RSA_SHA1: 114 | return Signature.getInstance("SHA1withRSA"); 115 | case RSA_SHA256: 116 | return Signature.getInstance("SHA256withRSA"); 117 | case RSA_SHA512: 118 | return Signature.getInstance("SHA512withRSA"); 119 | case DSA_SHA1: 120 | return Signature.getInstance("SHA1withDSA"); 121 | default: 122 | return null; 123 | } 124 | } catch (NoSuchAlgorithmException e) { 125 | LOGGER.error("[getSignatureInstance] failed to get signature instance.", e); 126 | } 127 | } 128 | 129 | return null; 130 | } 131 | 132 | public static KeyFormat forIdentifier(String identifier) { 133 | for (KeyFormat format : KeyFormat.values()) { 134 | if (format.getIdentifier().equals(identifier)) { 135 | return format; 136 | } 137 | } 138 | 139 | return UNKOWN; 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /ssh-jsch/src/test/java/net/adamcin/httpsig/ssh/jsch/JschKeyTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.ssh.jsch; 29 | 30 | import com.jcraft.jsch.JSch; 31 | import net.adamcin.commons.testing.junit.FailUtil; 32 | import net.adamcin.httpsig.api.Authorization; 33 | import net.adamcin.httpsig.api.Challenge; 34 | import net.adamcin.httpsig.api.Constants; 35 | import net.adamcin.httpsig.api.DefaultKeychain; 36 | import net.adamcin.httpsig.api.DefaultVerifier; 37 | import net.adamcin.httpsig.api.Keychain; 38 | import net.adamcin.httpsig.api.RequestContent; 39 | import net.adamcin.httpsig.api.Signer; 40 | import net.adamcin.httpsig.ssh.jce.AuthorizedKeys; 41 | import net.adamcin.httpsig.ssh.jce.KeyFormat; 42 | import net.adamcin.httpsig.ssh.jce.SSHKey; 43 | import net.adamcin.httpsig.testutil.KeyTestUtil; 44 | import org.apache.commons.io.IOUtils; 45 | import org.junit.Test; 46 | import org.slf4j.Logger; 47 | import org.slf4j.LoggerFactory; 48 | 49 | import java.io.Reader; 50 | import java.util.Arrays; 51 | 52 | import static org.junit.Assert.assertEquals; 53 | import static org.junit.Assert.assertTrue; 54 | 55 | public class JschKeyTest { 56 | 57 | private static final Logger LOGGER = LoggerFactory.getLogger(JschKeyTest.class); 58 | 59 | @Test 60 | public void testSignature() { 61 | 62 | Reader reader = null; 63 | try { 64 | roundTrip(KeyFormat.SSH_RSA, "b1024", "id_rsa", null); 65 | roundTrip(KeyFormat.SSH_DSS, "b1024", "id_dsa", null); 66 | roundTrip(KeyFormat.SSH_RSA, "b2048", "id_rsa", null); 67 | roundTrip(KeyFormat.SSH_RSA, "b4096", "id_rsa", null); 68 | roundTrip(KeyFormat.SSH_DSS, "withpass", "id_dsa", "dummydummy"); 69 | roundTrip(KeyFormat.SSH_RSA, "withpass", "id_rsa", "dummydummy"); 70 | } catch (Exception e) { 71 | FailUtil.sprintFail(e); 72 | } finally { 73 | IOUtils.closeQuietly(reader); 74 | } 75 | } 76 | 77 | public void roundTrip(KeyFormat format, String parentName, String keyName, String passphrase) 78 | throws Exception { 79 | 80 | final String id = "[" + parentName + "/" + keyName + "] "; 81 | 82 | DefaultVerifier dverifier = new DefaultVerifier(AuthorizedKeys.newKeychain(KeyTestUtil.getPublicKeyAsFile(parentName, keyName))); 83 | String fingerprint = dverifier.getKeychain().currentKey().getId(); 84 | 85 | Challenge challenge = new Challenge("myRealm", Constants.DEFAULT_HEADERS, format.getSignatureAlgorithms()); 86 | 87 | JSch jSchSigner = new JSch(); 88 | 89 | jSchSigner.addIdentity(KeyTestUtil.getPrivateKeyAsFile(parentName, keyName).getAbsolutePath(), passphrase); 90 | 91 | Keychain sprovider = JschKey.getIdentities(jSchSigner); 92 | 93 | assertEquals(id + "sprovider should contain only one identity", 1, sprovider.toMap(null).size()); 94 | assertEquals(id + "fingerprints should match", fingerprint, sprovider.iterator().next().getId()); 95 | 96 | Signer jsigner = new Signer(sprovider); 97 | DefaultVerifier jverifier = new DefaultVerifier(sprovider); 98 | RequestContent requestContent = new RequestContent.Builder().addDateNow().build(); 99 | 100 | Signer dsigner = new Signer(new DefaultKeychain( 101 | Arrays.asList(new SSHKey(format, KeyTestUtil.getKeyPairFromProperties(parentName, keyName))))); 102 | 103 | jsigner.rotateKeys(challenge); 104 | Authorization jpacket = jsigner.sign(requestContent); 105 | 106 | dsigner.rotateKeys(challenge); 107 | Authorization dpacket = dsigner.sign(requestContent); 108 | 109 | LOGGER.info(id + "jpacket={}, dpacket={}", KeyTestUtil.bytesToHex(jpacket.getSignatureBytes()), 110 | KeyTestUtil.bytesToHex(dpacket.getSignatureBytes())); 111 | 112 | assertEquals(id + "jce fingerprints should match", fingerprint, dsigner.getKeychain().currentKey().getId()); 113 | assertTrue(id + "round trip using jce identities", dverifier.verify(challenge, requestContent, dpacket)); 114 | assertTrue(id + "round trip using JschIdentities", jverifier.verify(challenge, requestContent, jpacket)); 115 | 116 | assertTrue(id + "round trip using jverifier + dsigner", jverifier.verify(challenge, requestContent, dpacket)); 117 | assertTrue(id + "round trip using dverifier + jsigner", dverifier.verify(challenge, requestContent, jpacket)); 118 | } 119 | 120 | } 121 | -------------------------------------------------------------------------------- /ssh-bc/src/main/java/net/adamcin/httpsig/ssh/bc/PEMUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.ssh.bc; 29 | 30 | import net.adamcin.httpsig.api.Key; 31 | import net.adamcin.httpsig.ssh.jce.SSHKey; 32 | import net.adamcin.httpsig.ssh.jce.KeyFormat; 33 | import org.bouncycastle.openssl.PEMDecryptorProvider; 34 | import org.bouncycastle.openssl.PEMEncryptedKeyPair; 35 | import org.bouncycastle.openssl.PEMKeyPair; 36 | import org.bouncycastle.openssl.PEMParser; 37 | import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; 38 | import org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder; 39 | 40 | import java.io.ByteArrayInputStream; 41 | import java.io.File; 42 | import java.io.FileInputStream; 43 | import java.io.IOException; 44 | import java.io.InputStream; 45 | import java.io.InputStreamReader; 46 | import java.security.KeyPair; 47 | import java.security.interfaces.DSAPrivateKey; 48 | import java.security.interfaces.DSAPublicKey; 49 | import java.security.interfaces.RSAPrivateKey; 50 | import java.security.interfaces.RSAPublicKey; 51 | import java.util.logging.Logger; 52 | 53 | public class PEMUtil { 54 | private static final Logger LOGGER = Logger.getLogger(PEMUtil.class.getName()); 55 | 56 | /** 57 | * Read a single PEM-formatted key 58 | * @param is input stream 59 | * @param passphrase passphrase protecting stream 60 | * @return the key if successful, null if not 61 | * @throws IOException if not successful because I/O 62 | */ 63 | public static Key readKey(InputStream is, final char[] passphrase) throws IOException { 64 | JcaPEMKeyConverter converter = new JcaPEMKeyConverter(); 65 | PEMParser parser = null; 66 | KeyPair keyPair = null; 67 | 68 | try { 69 | parser = new PEMParser(new InputStreamReader(is)); 70 | 71 | Object o = parser.readObject(); 72 | if (o instanceof PEMEncryptedKeyPair) { 73 | PEMEncryptedKeyPair _encPair = (PEMEncryptedKeyPair) o; 74 | PEMDecryptorProvider decryptionProv = new JcePEMDecryptorProviderBuilder().build(passphrase); 75 | keyPair = converter.getKeyPair(_encPair.decryptKeyPair(decryptionProv)); 76 | } else if (o instanceof PEMKeyPair) { 77 | keyPair = converter.getKeyPair((PEMKeyPair) o); 78 | } 79 | 80 | if (keyPair != null) { 81 | if (keyPair.getPrivate() instanceof RSAPrivateKey 82 | || keyPair.getPublic() instanceof RSAPublicKey) { 83 | return new SSHKey(KeyFormat.SSH_RSA, keyPair); 84 | } else if (keyPair.getPrivate() instanceof DSAPrivateKey 85 | || keyPair.getPublic() instanceof DSAPublicKey) { 86 | return new SSHKey(KeyFormat.SSH_DSS, keyPair); 87 | } 88 | } 89 | 90 | return null; 91 | 92 | } finally { 93 | if (parser != null) { 94 | try { parser.close(); } catch (IOException ignored) {} 95 | } 96 | } 97 | } 98 | 99 | /** 100 | * 101 | * Read a single PEM-formatted key 102 | * @param privateKeyFile private key file 103 | * @param passphrase passphrase for protected file 104 | * @return key if successful 105 | * @throws IOException if not successful 106 | */ 107 | public static Key readKey(File privateKeyFile, final char[] passphrase) throws IOException { 108 | InputStream is = null; 109 | 110 | try { 111 | is = new FileInputStream(privateKeyFile); 112 | return readKey(is, passphrase); 113 | } finally { 114 | if (is != null) { 115 | try { is.close(); } catch (IOException ignored) {} 116 | } 117 | } 118 | } 119 | 120 | /** 121 | * 122 | * Read a single PEM-formatted key 123 | * @param keyBytes data for key 124 | * @param passphrase passphrase 125 | * @return key if successful 126 | * @throws IOException if not successful 127 | */ 128 | public static Key readKey(byte[] keyBytes, final char[] passphrase) throws IOException { 129 | ByteArrayInputStream is = null; 130 | 131 | try { 132 | is = new ByteArrayInputStream(keyBytes); 133 | return readKey(is, passphrase); 134 | } finally { 135 | if (is != null) { 136 | try { is.close(); } catch (IOException ignored) {} 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /test-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 28 | 29 | 30 | 4.0.0 31 | 32 | 33 | net.adamcin.httpsig 34 | httpsig 35 | 1.3.2-SNAPSHOT 36 | .. 37 | 38 | 39 | httpsig-test-common 40 | jar 41 | 42 | ${project.artifactId} 43 | 44 | Library containing common testing resources and methods for the httpsig suite 45 | 46 | 47 | 2013 48 | 49 | 50 | https://github.com/adamcin/httpsig-java 51 | scm:git:git@github.com:adamcin/httpsig-java.git 52 | scm:git://github.com/adamcin/httpsig-java.git 53 | HEAD 54 | 55 | 56 | 57 | 58 | 59 | org.codehaus.mojo 60 | templating-maven-plugin 61 | 62 | 63 | org.apache.maven.plugins 64 | maven-compiler-plugin 65 | 66 | 67 | org.apache.felix 68 | maven-scr-plugin 69 | 70 | 71 | 72 | scr 73 | 74 | 75 | 76 | 77 | 78 | com.github.github 79 | site-maven-plugin 80 | 81 | Creating site for ${project.artifactId} ${project.version} 82 | true 83 | adamcin 84 | httpsig-java 85 | ${project.artifactId} 86 | true 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | net.adamcin.httpsig 96 | httpsig-api 97 | compile 98 | 99 | 100 | net.adamcin.commons 101 | net.adamcin.commons.testing 102 | compile 103 | 104 | 105 | org.bouncycastle 106 | bcprov-jdk15on 107 | compile 108 | 109 | 110 | org.bouncycastle 111 | bcpkix-jdk15on 112 | compile 113 | 114 | 115 | junit 116 | junit 117 | compile 118 | 119 | 120 | org.slf4j 121 | slf4j-api 122 | compile 123 | 124 | 125 | commons-io 126 | commons-io 127 | compile 128 | 129 | 130 | 131 | biz.aQute.bnd 132 | bndlib 133 | provided 134 | 135 | 136 | 137 | org.slf4j 138 | slf4j-simple 139 | test 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /api/src/test/java/net/adamcin/httpsig/api/ConstantsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This is free and unencumbered software released into the public domain. 3 | * 4 | * Anyone is free to copy, modify, publish, use, compile, sell, or 5 | * distribute this software, either in source code form or as a compiled 6 | * binary, for any purpose, commercial or non-commercial, and by any 7 | * means. 8 | * 9 | * In jurisdictions that recognize copyright laws, the author or authors 10 | * of this software dedicate any and all copyright interest in the 11 | * software to the public domain. We make this dedication for the benefit 12 | * of the public at large and to the detriment of our heirs and 13 | * successors. We intend this dedication to be an overt act of 14 | * relinquishment in perpetuity of all present and future rights to this 15 | * software under copyright law. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | * 25 | * For more information, please refer to 26 | */ 27 | 28 | package net.adamcin.httpsig.api; 29 | 30 | import org.junit.Test; 31 | 32 | import java.util.*; 33 | 34 | import static org.junit.Assert.assertEquals; 35 | 36 | public class ConstantsTest { 37 | 38 | /** 39 | * Added for defect-2; Provided test case {@code headers="date content-type"} 40 | */ 41 | @Test 42 | public void testConstructTokensString() { 43 | 44 | assertEquals("headers should be empty if provided with a null list", "", 45 | Constants.constructTokensString(null)); 46 | 47 | assertEquals("headers should be empty if provided with an empty list", "", 48 | Constants.constructTokensString(Collections.emptyList())); 49 | 50 | assertEquals("should be a single token with no leading or trailing whitespace", "date", 51 | Constants.constructTokensString(Arrays.asList("date"))); 52 | 53 | assertEquals("headers should be separated by one space with no trailing spaces", "date content-type", 54 | Constants.constructTokensString(Arrays.asList("date", "content-type"))); 55 | } 56 | 57 | /** 58 | * Added for defect-2; should support new and old formats 59 | * Provided test case {@code headers="date content-type"} which should remain equivalent to 60 | * {@code headers="date content-type "} 61 | */ 62 | @Test 63 | public void testParseTokens() { 64 | List tokens = Arrays.asList("date", "content-type"); 65 | List parsedExpected = Constants.parseTokens("date content-type"); 66 | assertEquals("expected format should parse correctly", tokens, parsedExpected); 67 | 68 | List parsedLegacy = Constants.parseTokens("date content-type "); 69 | assertEquals("legacy format should parse correctly", tokens, parsedLegacy); 70 | } 71 | 72 | /** 73 | * Added for defect-2; Provided test case: 74 | * {@code Signature keyId="unit", algorithm="hmac-sha1", headers="Content-Type Date", signature="8sY4dne3lta76PDMM+AUVaKkV7o="} 75 | * which should be 76 | * {@code Signature keyId="unit",algorithm="hmac-sha1",headers="Content-Type Date",signature="yIy5ujWnGZ0pKVR7vY6Qv08WfLE="} 77 | */ 78 | @Test 79 | public void testConstructRFC2617() { 80 | Map params = new LinkedHashMap(); 81 | params.put("keyId", "unit"); 82 | params.put("algorithm", "hmac-sha1"); 83 | params.put("headers", "Content-Type Date"); 84 | params.put("signature", "yIy5ujWnGZ0pKVR7vY6Qv08WfLE="); 85 | 86 | String formatted = Constants.constructRFC2617(params); 87 | 88 | assertEquals("RFC 2617 string should be properly formatted", 89 | "Signature keyId=\"unit\",algorithm=\"hmac-sha1\",headers=\"Content-Type Date\",signature=\"yIy5ujWnGZ0pKVR7vY6Qv08WfLE=\"", 90 | formatted); 91 | } 92 | 93 | /** 94 | * Added for defect-2; maintain support for both new and old formats. 95 | * {@code Signature keyId="unit", algorithm="hmac-sha1", headers="Content-Type Date", signature="8sY4dne3lta76PDMM+AUVaKkV7o="} 96 | * {@code Signature keyId="unit",algorithm="hmac-sha1",headers="Content-Type Date",signature="yIy5ujWnGZ0pKVR7vY6Qv08WfLE="} 97 | */ 98 | @Test 99 | public void testParseRFC2617() { 100 | final String expectedFormat = "Signature keyId=\"unit\",algorithm=\"hmac-sha1\",headers=\"Content-Type Date\",signature=\"yIy5ujWnGZ0pKVR7vY6Qv08WfLE=\""; 101 | final String legacyFormat = "Signature keyId=\"unit\", algorithm=\"hmac-sha1\", headers=\"Content-Type Date\", signature=\"yIy5ujWnGZ0pKVR7vY6Qv08WfLE=\""; 102 | 103 | Map params = new LinkedHashMap(); 104 | params.put("keyId", "unit"); 105 | params.put("algorithm", "hmac-sha1"); 106 | params.put("headers", "Content-Type Date"); 107 | params.put("signature", "yIy5ujWnGZ0pKVR7vY6Qv08WfLE="); 108 | 109 | Map parsedExpected = Constants.parseRFC2617(expectedFormat); 110 | for (Map.Entry entry : params.entrySet()) { 111 | assertEquals("parsed param values should be the same", entry.getValue(), parsedExpected.get(entry.getKey())); 112 | } 113 | 114 | Map parsedLegacy = Constants.parseRFC2617(legacyFormat); 115 | for (Map.Entry entry : params.entrySet()) { 116 | assertEquals("parsed param values should be the same", entry.getValue(), parsedLegacy.get(entry.getKey())); 117 | } 118 | } 119 | } 120 | --------------------------------------------------------------------------------