github.com/psiphon-Labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/accesscontrol/accesscontrol_test.go (about) 1 /* 2 * Copyright (c) 2018, Psiphon Inc. 3 * All rights reserved. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package accesscontrol 21 22 import ( 23 "encoding/base64" 24 "encoding/json" 25 "fmt" 26 "testing" 27 "time" 28 ) 29 30 func TestAuthorization(t *testing.T) { 31 32 correctAccess := "access1" 33 otherAccess := "access2" 34 35 correctSigningKey, correctVerificationKey, err := NewKeyPair(correctAccess) 36 if err != nil { 37 t.Fatalf("NewKeyPair failed: %s", err) 38 } 39 40 otherSigningKey, otherVerificationKey, err := NewKeyPair(otherAccess) 41 if err != nil { 42 t.Fatalf("NewKeyPair failed: %s", err) 43 } 44 45 invalidSigningKey, _, err := NewKeyPair(correctAccess) 46 if err != nil { 47 t.Fatalf("NewKeyPair failed: %s", err) 48 } 49 50 keyRing := &VerificationKeyRing{ 51 Keys: []*VerificationKey{correctVerificationKey, otherVerificationKey}, 52 } 53 54 // Test: valid key 55 56 err = ValidateSigningKey(correctSigningKey) 57 if err != nil { 58 t.Fatalf("ValidateSigningKey failed: %s", err) 59 } 60 61 // Test: invalid key 62 63 err = ValidateSigningKey(&SigningKey{}) 64 if err == nil { 65 t.Fatalf("ValidateSigningKey unexpected success") 66 } 67 68 // Test: valid key ring 69 70 err = ValidateVerificationKeyRing(keyRing) 71 if err != nil { 72 t.Fatalf("ValidateVerificationKeyRing failed: %s", err) 73 } 74 75 // Test: invalid key ring 76 77 invalidKeyRing := &VerificationKeyRing{ 78 Keys: []*VerificationKey{&VerificationKey{}}, 79 } 80 81 err = ValidateVerificationKeyRing(invalidKeyRing) 82 if err == nil { 83 t.Fatalf("ValidateVerificationKeyRing unexpected success") 84 } 85 86 // Test: valid authorization 87 88 id := []byte("0000000000000001") 89 90 expires := time.Now().Add(10 * time.Second) 91 92 auth, issuedID, err := IssueAuthorization(correctSigningKey, id, expires) 93 if err != nil { 94 t.Fatalf("IssueAuthorization failed: %s", err) 95 } 96 97 // Test: re-issuing authorization with the same seedAuthorizationID yields 98 // the same value 99 100 reauth, _, err := IssueAuthorization(correctSigningKey, id, expires) 101 if err != nil { 102 t.Fatalf("IssueAuthorization failed: %s", err) 103 } 104 105 if auth != reauth { 106 t.Fatalf("unexpected difference in authorizations") 107 } 108 109 // Decode the signed authorization and check that the auth ID in the JSON 110 // matches the one returned by IssueAuthorization. 111 112 decodedAuthorization, err := base64.StdEncoding.DecodeString(auth) 113 if err != nil { 114 t.Fatalf("DecodeString failed: %s", err) 115 } 116 117 type partialSignedAuthorization struct { 118 Authorization json.RawMessage 119 } 120 var partialSignedAuth partialSignedAuthorization 121 err = json.Unmarshal(decodedAuthorization, &partialSignedAuth) 122 if err != nil { 123 t.Fatalf("Unmarshal failed: %s", err) 124 } 125 126 var unmarshaledAuth map[string]interface{} 127 err = json.Unmarshal(partialSignedAuth.Authorization, &unmarshaledAuth) 128 if err != nil { 129 t.Fatalf("Unmarshal failed: %s", err) 130 } 131 132 authID, ok := unmarshaledAuth["ID"].(string) 133 if !ok { 134 t.Fatalf("Failed to find auth ID in unmarshaled auth: %s", unmarshaledAuth) 135 } 136 137 if string(authID) != base64.StdEncoding.EncodeToString(issuedID) { 138 t.Fatalf("Expected auth ID in signed auth (%s) to match that returned by IssueAuthorization (%s)", string(authID), base64.StdEncoding.EncodeToString(issuedID)) 139 } 140 141 fmt.Printf("encoded authorization length: %d\n", len(auth)) 142 143 verifiedAuth, err := VerifyAuthorization(keyRing, auth) 144 if err != nil { 145 t.Fatalf("VerifyAuthorization failed: %s", err) 146 } 147 148 if verifiedAuth.AccessType != correctAccess { 149 t.Fatalf("unexpected access type: %s", verifiedAuth.AccessType) 150 } 151 152 // Test: expired authorization 153 154 expires = time.Now().Add(-10 * time.Second) 155 156 auth, _, err = IssueAuthorization(correctSigningKey, id, expires) 157 if err != nil { 158 t.Fatalf("IssueAuthorization failed: %s", err) 159 } 160 161 _, err = VerifyAuthorization(keyRing, auth) 162 // TODO: check error message? 163 if err == nil { 164 t.Fatalf("VerifyAuthorization unexpected success") 165 } 166 167 // Test: authorization signed with key not in key ring 168 169 expires = time.Now().Add(10 * time.Second) 170 171 auth, _, err = IssueAuthorization(invalidSigningKey, id, expires) 172 if err != nil { 173 t.Fatalf("IssueAuthorization failed: %s", err) 174 } 175 176 _, err = VerifyAuthorization(keyRing, auth) 177 // TODO: check error message? 178 if err == nil { 179 t.Fatalf("VerifyAuthorization unexpected success") 180 } 181 182 // Test: authorization signed with valid key, but hacked access type 183 184 expires = time.Now().Add(10 * time.Second) 185 186 auth, _, err = IssueAuthorization(otherSigningKey, id, expires) 187 if err != nil { 188 t.Fatalf("IssueAuthorization failed: %s", err) 189 } 190 191 decodedAuth, err := base64.StdEncoding.DecodeString(auth) 192 if err != nil { 193 t.Fatalf("DecodeString failed: %s", err) 194 } 195 196 var hackSignedAuth signedAuthorization 197 err = json.Unmarshal(decodedAuth, &hackSignedAuth) 198 if err != nil { 199 t.Fatalf("Unmarshal failed: %s", err) 200 } 201 202 var hackAuth Authorization 203 err = json.Unmarshal(hackSignedAuth.Authorization, &hackAuth) 204 if err != nil { 205 t.Fatalf("Unmarshal failed: %s", err) 206 } 207 208 hackAuth.AccessType = correctAccess 209 210 marshaledAuth, err := json.Marshal(hackAuth) 211 if err != nil { 212 t.Fatalf("Marshall failed: %s", err) 213 } 214 215 hackSignedAuth.Authorization = marshaledAuth 216 217 marshaledSignedAuth, err := json.Marshal(hackSignedAuth) 218 if err != nil { 219 t.Fatalf("Marshall failed: %s", err) 220 } 221 222 encodedSignedAuth := base64.StdEncoding.EncodeToString(marshaledSignedAuth) 223 224 _, err = VerifyAuthorization(keyRing, encodedSignedAuth) 225 // TODO: check error message? 226 if err == nil { 227 t.Fatalf("VerifyAuthorization unexpected success") 228 } 229 }