AbstractHafasClientInterfaceProvider: Derive checksum and mic/mac salts.

This commit is contained in:
Andreas Schildbach 2019-01-05 14:21:52 +01:00
parent 2390da90d6
commit c5b140b073
10 changed files with 44 additions and 20 deletions

View file

@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
@ -39,6 +40,9 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.json.JSONArray;
import org.json.JSONException;
@ -980,4 +984,19 @@ public abstract class AbstractHafasClientInterfaceProvider extends AbstractHafas
return earlierContext != null;
}
}
public static final byte[] decryptSalt(final String encryptedSalt, final String saltEncryptionKey) {
try {
final byte[] key = BaseEncoding.base16().lowerCase().decode(saltEncryptionKey);
checkState(key.length * 8 == 128, "encryption key must be 128 bits");
final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
final IvParameterSpec ivParameterSpec = new IvParameterSpec(new byte[16]);
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
return cipher.doFinal(BaseEncoding.base64().decode(encryptedSalt));
} catch (final GeneralSecurityException x) {
// should not happen
throw new RuntimeException(x);
}
}
}

View file

@ -21,8 +21,6 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.base.Charsets;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
@ -38,13 +36,13 @@ public final class DbProvider extends AbstractHafasClientInterfaceProvider {
Product.REGIONAL_TRAIN, Product.REGIONAL_TRAIN, Product.SUBURBAN_TRAIN, Product.BUS, Product.FERRY,
Product.SUBWAY, Product.TRAM, Product.ON_DEMAND, null, null, null, null };
public DbProvider(final String apiAuthorization) {
public DbProvider(final String apiAuthorization, final byte[] salt) {
super(NetworkId.DB, API_BASE, PRODUCTS_MAP);
setApiVersion("1.14");
setApiExt("DB.R15.12.a");
setApiClient("{\"id\":\"DB\",\"v\":\"16040000\",\"type\":\"AND\",\"name\":\"DB Navigator\"}");
setApiAuthorization(apiAuthorization);
setRequestChecksumSalt("bdI8UVj40K5fvxwf".getBytes(Charsets.UTF_8));
setRequestChecksumSalt(salt);
}
@Override

View file

@ -21,8 +21,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import com.google.common.base.Charsets;
import de.schildbach.pte.dto.Product;
import de.schildbach.pte.dto.Style;
@ -37,12 +35,12 @@ public class InvgProvider extends AbstractHafasClientInterfaceProvider {
private static final HttpUrl API_BASE = HttpUrl.parse("https://fpa.invg.de/bin/");
private static final Product[] PRODUCTS_MAP = { Product.BUS, null, null, Product.REGIONAL_TRAIN };
public InvgProvider(final String apiAuthorization) {
public InvgProvider(final String apiAuthorization, final byte[] salt) {
super(NetworkId.INVG, API_BASE, PRODUCTS_MAP);
setApiVersion("1.14");
setApiClient("{\"id\":\"INVG\",\"type\":\"AND\"}");
setApiAuthorization(apiAuthorization);
setRequestMicMacSalt("ERxotxpwFT7uYRsI".getBytes(Charsets.UTF_8));
setRequestMicMacSalt(salt);
setStyles(STYLES);
}

View file

@ -22,8 +22,6 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.io.BaseEncoding;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
@ -40,12 +38,12 @@ public class VbbProvider extends AbstractHafasClientInterfaceProvider {
private static final Set<Product> ALL_EXCEPT_HIGHSPEED_AND_ONDEMAND = EnumSet
.complementOf(EnumSet.of(Product.HIGH_SPEED_TRAIN, Product.ON_DEMAND));
public VbbProvider(final String apiAuthorization) {
public VbbProvider(final String apiAuthorization, final byte[] salt) {
super(NetworkId.VBB, API_BASE, PRODUCTS_MAP);
setApiVersion("1.14");
setApiClient("{\"id\":\"VBB\",\"type\":\"AND\"}");
setApiAuthorization(apiAuthorization);
setRequestMicMacSalt(BaseEncoding.base16().lowerCase().decode("5243544a4d3266467846667878516649"));
setRequestMicMacSalt(salt);
httpClient.setTrustAllCertificates(true);
}

View file

@ -19,8 +19,6 @@ package de.schildbach.pte;
import java.util.regex.Matcher;
import com.google.common.base.Charsets;
import de.schildbach.pte.dto.Product;
import okhttp3.HttpUrl;
@ -36,12 +34,12 @@ public class VgsProvider extends AbstractHafasClientInterfaceProvider {
Product.HIGH_SPEED_TRAIN, Product.REGIONAL_TRAIN, Product.SUBURBAN_TRAIN, Product.SUBWAY, Product.TRAM,
Product.BUS, Product.CABLECAR, Product.ON_DEMAND, Product.BUS };
public VgsProvider(final String jsonApiAuthorization) {
public VgsProvider(final String jsonApiAuthorization, final byte[] salt) {
super(NetworkId.VGS, API_BASE, PRODUCTS_MAP);
setApiVersion("1.21");
setApiClient("{\"id\":\"ZPS-SAAR\",\"type\":\"AND\"}");
setApiAuthorization(jsonApiAuthorization);
setRequestMicMacSalt("HJtlubisvxiJxss".getBytes(Charsets.UTF_8));
setRequestMicMacSalt(salt);
}
@Override

View file

@ -26,6 +26,7 @@ import java.util.EnumSet;
import org.junit.Test;
import de.schildbach.pte.AbstractHafasClientInterfaceProvider;
import de.schildbach.pte.DbProvider;
import de.schildbach.pte.NetworkProvider.Accessibility;
import de.schildbach.pte.NetworkProvider.WalkSpeed;
@ -44,7 +45,8 @@ import de.schildbach.pte.dto.TripOptions;
*/
public class DbProviderLiveTest extends AbstractProviderLiveTest {
public DbProviderLiveTest() {
super(new DbProvider(secretProperty("db.api_authorization")));
super(new DbProvider(secretProperty("db.api_authorization"), AbstractHafasClientInterfaceProvider
.decryptSalt(secretProperty("db.encrypted_salt"), secretProperty("hci.salt_encryption_key"))));
}
@Test

View file

@ -23,6 +23,7 @@ import java.util.Date;
import org.junit.Test;
import de.schildbach.pte.AbstractHafasClientInterfaceProvider;
import de.schildbach.pte.InvgProvider;
import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.LocationType;
@ -36,7 +37,8 @@ import de.schildbach.pte.dto.SuggestLocationsResult;
*/
public class InvgProviderLiveTest extends AbstractProviderLiveTest {
public InvgProviderLiveTest() {
super(new InvgProvider(secretProperty("invg.api_authorization")));
super(new InvgProvider(secretProperty("invg.api_authorization"), AbstractHafasClientInterfaceProvider
.decryptSalt(secretProperty("invg.encrypted_salt"), secretProperty("hci.salt_encryption_key"))));
}
@Test

View file

@ -26,6 +26,7 @@ import java.util.Date;
import org.junit.Assert;
import org.junit.Test;
import de.schildbach.pte.AbstractHafasClientInterfaceProvider;
import de.schildbach.pte.VbbProvider;
import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.LocationType;
@ -40,7 +41,8 @@ import de.schildbach.pte.dto.SuggestLocationsResult;
*/
public class VbbProviderLiveTest extends AbstractProviderLiveTest {
public VbbProviderLiveTest() {
super(new VbbProvider(secretProperty("vbb.api_authorization")));
super(new VbbProvider(secretProperty("vbb.api_authorization"), AbstractHafasClientInterfaceProvider
.decryptSalt(secretProperty("vbb.encrypted_salt"), secretProperty("hci.salt_encryption_key"))));
}
@Test

View file

@ -23,6 +23,7 @@ import java.util.Date;
import org.junit.Test;
import de.schildbach.pte.AbstractHafasClientInterfaceProvider;
import de.schildbach.pte.VgsProvider;
import de.schildbach.pte.dto.Location;
import de.schildbach.pte.dto.LocationType;
@ -36,7 +37,8 @@ import de.schildbach.pte.dto.SuggestLocationsResult;
*/
public class VgsProviderLiveTest extends AbstractProviderLiveTest {
public VgsProviderLiveTest() {
super(new VgsProvider(secretProperty("vgs.api_authorization")));
super(new VgsProvider(secretProperty("vgs.api_authorization"), AbstractHafasClientInterfaceProvider
.decryptSalt(secretProperty("vgs.encrypted_salt"), secretProperty("hci.salt_encryption_key"))));
}
@Test

View file

@ -1,15 +1,20 @@
# Secrets are needed to run some of the live tests.
navitia.authorization =
hci.salt_encryption_key =
db.api_authorization =
db.encrypted_salt =
bvg.api_authorization =
vbb.api_authorization =
vbb.encrypted_salt =
nvv.api_authorization =
sh.api_authorization =
vbn.api_authorization =
nasa.api_authorization =
vgs.api_authorization =
vgs.encrypted_salt =
vmt.api_authorization =
invg.api_authorization =
invg.encrypted_salt =
avv_aachen.api_authorization =
oebb.api_authorization =
vor.api_authorization =