update
This commit is contained in:
parent
430a04837f
commit
8d227b26d3
4 changed files with 233 additions and 110 deletions
|
|
@ -57,7 +57,8 @@ public class StartupValidator implements ApplicationContextInitializer<Configura
|
||||||
|
|
||||||
responseCode = LicenseUtils.request(env.getProperty("license-server-endpoint"), resource.getInputStream(),
|
responseCode = LicenseUtils.request(env.getProperty("license-server-endpoint"), resource.getInputStream(),
|
||||||
env.getProperty("license-server-trust-password"),
|
env.getProperty("license-server-trust-password"),
|
||||||
env.getProperty("my-id") + "." + encrypted + "." + signature);
|
Base64.getUrlEncoder()
|
||||||
|
.encodeToString(env.getProperty("my-id").getBytes()) + "." + encrypted + "." + signature);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new IllegalStateException("IO exception for trust store!", e);
|
throw new IllegalStateException("IO exception for trust store!", e);
|
||||||
}
|
}
|
||||||
|
|
@ -86,12 +87,14 @@ public class StartupValidator implements ApplicationContextInitializer<Configura
|
||||||
properties.setProperty("index", "");
|
properties.setProperty("index", "");
|
||||||
saveProperties(properties, filePath);
|
saveProperties(properties, filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveProperties(Properties properties,
|
private void saveProperties(Properties properties,
|
||||||
String filePath) throws IOException {
|
String filePath) throws IOException {
|
||||||
try (FileOutputStream fos = new FileOutputStream(filePath)) {
|
try (FileOutputStream fos = new FileOutputStream(filePath)) {
|
||||||
properties.store(fos, "Updated properties file");
|
properties.store(fos, "Updated properties file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadProperties(Properties properties,
|
private void loadProperties(Properties properties,
|
||||||
String filePath) throws IOException {
|
String filePath) throws IOException {
|
||||||
try (FileInputStream fis = new FileInputStream(filePath)) {
|
try (FileInputStream fis = new FileInputStream(filePath)) {
|
||||||
|
|
|
||||||
|
|
@ -143,8 +143,10 @@ public final class KeyUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt data using AES-GCM
|
// Decrypt data using AES-GCM
|
||||||
private static String decryptDataWithAESGCM(byte[] encryptedDataWithIv,
|
public static String decryptDataWithAESGCM(byte[] encryptedDataWithIv,
|
||||||
SecretKey sharedSecret) throws Exception {
|
SecretKey sharedSecret) {
|
||||||
|
|
||||||
|
try {
|
||||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||||
|
|
||||||
// Extract IV
|
// Extract IV
|
||||||
|
|
@ -159,6 +161,19 @@ public final class KeyUtils {
|
||||||
byte[] decryptedData = cipher.doFinal(encryptedData);
|
byte[] decryptedData = cipher.doFinal(encryptedData);
|
||||||
|
|
||||||
return new String(decryptedData);
|
return new String(decryptedData);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("NoSuchAlgorithmException!", e);
|
||||||
|
} catch (NoSuchPaddingException e) {
|
||||||
|
throw new RuntimeException("NoSuchPaddingException!", e);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new RuntimeException("InvalidKeyException!", e);
|
||||||
|
} catch (InvalidAlgorithmParameterException e) {
|
||||||
|
throw new RuntimeException("InvalidAlgorithmParameterException!", e);
|
||||||
|
} catch (IllegalBlockSizeException e) {
|
||||||
|
throw new RuntimeException("IllegalBlockSizeException!", e);
|
||||||
|
} catch (BadPaddingException e) {
|
||||||
|
throw new RuntimeException("BadPaddingException!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String privateKeyToString(PrivateKey privateKey) {
|
private static String privateKeyToString(PrivateKey privateKey) {
|
||||||
|
|
@ -218,14 +233,22 @@ public final class KeyUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the signature
|
// Verify the signature
|
||||||
private static boolean verifySignature(String message,
|
public static boolean verifySignature(String message,
|
||||||
String signatureStr,
|
String signatureStr,
|
||||||
PublicKey publicKey) throws Exception {
|
PublicKey publicKey) {
|
||||||
|
try {
|
||||||
Signature signature = Signature.getInstance("SHA256withECDSA");
|
Signature signature = Signature.getInstance("SHA256withECDSA");
|
||||||
signature.initVerify(publicKey);
|
signature.initVerify(publicKey);
|
||||||
signature.update(message.getBytes());
|
signature.update(message.getBytes());
|
||||||
byte[] signatureBytes = Base64.getUrlDecoder()
|
byte[] signatureBytes = Base64.getUrlDecoder()
|
||||||
.decode(signatureStr);
|
.decode(signatureStr);
|
||||||
return signature.verify(signatureBytes);
|
return signature.verify(signatureBytes);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("NoSuchAlgorithmException!", e);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new RuntimeException("InvalidKeyException!", e);
|
||||||
|
} catch (SignatureException e) {
|
||||||
|
throw new RuntimeException("SignatureException!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -4,6 +4,8 @@ import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
|
@ -14,6 +16,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import com.example.license.utils.DeterministicHexSequenceWithTimestamp;
|
import com.example.license.utils.DeterministicHexSequenceWithTimestamp;
|
||||||
|
import com.example.license.utils.KeyUtils;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/license")
|
@RequestMapping("/license")
|
||||||
|
|
@ -32,9 +35,10 @@ public class LicenseRest {
|
||||||
File directory = new File(licenseDirectory);
|
File directory = new File(licenseDirectory);
|
||||||
|
|
||||||
// TODO: extract ID, encrypted message and signature
|
// TODO: extract ID, encrypted message and signature
|
||||||
final var id = split[0];
|
final var id = new String(Base64.getUrlDecoder().decode(split[0]), StandardCharsets.UTF_8);
|
||||||
final var encrypted = split[1];
|
final var encrypted = split[1];
|
||||||
final var signature = split[2];
|
final var signature = split[2];
|
||||||
|
System.out.println("ID: " + id);
|
||||||
System.out.println("Encrypted: " + encrypted);
|
System.out.println("Encrypted: " + encrypted);
|
||||||
System.out.println("Signature: " + signature);
|
System.out.println("Signature: " + signature);
|
||||||
|
|
||||||
|
|
@ -47,18 +51,39 @@ public class LicenseRest {
|
||||||
final var filePath = licenseDirectory + File.separator + fileName;
|
final var filePath = licenseDirectory + File.separator + fileName;
|
||||||
final var props = loadProperties(filePath);
|
final var props = loadProperties(filePath);
|
||||||
|
|
||||||
//TODO: decrypt
|
final var decrypted = KeyUtils
|
||||||
|
.decryptDataWithAESGCM(Base64.getUrlDecoder().decode(encrypted),
|
||||||
|
KeyUtils.generateSharedSecret(
|
||||||
|
KeyUtils.stringToPrivateKey(props.getProperty("receiver-private-key")),
|
||||||
|
KeyUtils.stringToPublicKey(props.getProperty("sender-public-key"))));
|
||||||
|
System.out.println("Decrypted: " + decrypted);
|
||||||
|
|
||||||
// TODO: verify signature
|
// TODO: verify signature
|
||||||
|
boolean isVerified = KeyUtils.verifySignature(decrypted, signature,
|
||||||
|
KeyUtils.stringToPublicKey(props.getProperty("sender-public-key")));
|
||||||
|
System.out.println("Is verified? " + isVerified);
|
||||||
|
|
||||||
//TODO: veryfy current index match, increment index using timestamp then send new index in response.
|
// TODO: parse data
|
||||||
|
final var decryptedSplit = decrypted.split("\\:");
|
||||||
|
final var currentSenderIndex = decryptedSplit[0];
|
||||||
|
final var timestamp = Long.valueOf(decryptedSplit[1]);
|
||||||
|
final var currentLocalIndex = props.getProperty("index");
|
||||||
|
// TODO: check current local index if it matches with current sender index
|
||||||
|
final var nextLocalIndex = DeterministicHexSequenceWithTimestamp
|
||||||
|
.nextValueString(props.getProperty("index"), timestamp);
|
||||||
|
System.out.println("Current sender index: " + currentSenderIndex + " timestamp = " + timestamp
|
||||||
|
+ " current local index = " + currentLocalIndex + " next index = " + nextLocalIndex);
|
||||||
|
|
||||||
|
// TODO: veryfy current index match, increment index using timestamp then send
|
||||||
|
// new index in response.
|
||||||
System.out.println("Props: " + props);
|
System.out.println("Props: " + props);
|
||||||
System.out.println(props.getProperty("index"));
|
System.out.println(props.getProperty("index"));
|
||||||
if (!StringUtils.hasText(props.getProperty("index"))) {
|
if (!StringUtils.hasText(props.getProperty("index"))) {
|
||||||
props.setProperty("index", "1A3F");
|
props.setProperty("index", "1A3F");
|
||||||
saveProperties(filePath, props);
|
saveProperties(filePath, props);
|
||||||
} else {
|
} else {
|
||||||
props.setProperty("index", DeterministicHexSequenceWithTimestamp.nextValueString(props.getProperty("index"), 0));
|
props.setProperty("index", DeterministicHexSequenceWithTimestamp
|
||||||
|
.nextValueString(props.getProperty("index"), 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,27 @@
|
||||||
package com.example.license.utils;
|
package com.example.license.utils;
|
||||||
|
|
||||||
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
import java.security.KeyFactory;
|
import java.security.KeyFactory;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
import java.security.KeyPairGenerator;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
|
import java.security.SignatureException;
|
||||||
import java.security.spec.ECGenParameterSpec;
|
import java.security.spec.ECGenParameterSpec;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
|
import javax.crypto.BadPaddingException;
|
||||||
import javax.crypto.Cipher;
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.IllegalBlockSizeException;
|
||||||
import javax.crypto.KeyAgreement;
|
import javax.crypto.KeyAgreement;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.crypto.spec.GCMParameterSpec;
|
import javax.crypto.spec.GCMParameterSpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
@ -60,7 +68,7 @@ public final class KeyUtils {
|
||||||
|
|
||||||
// Print Results
|
// Print Results
|
||||||
System.out.println("Original Message: " + originalMessage);
|
System.out.println("Original Message: " + originalMessage);
|
||||||
System.out.println("Encrypted (Base64): " + Base64.getEncoder()
|
System.out.println("Encrypted (Base64): " + Base64.getUrlEncoder()
|
||||||
.encodeToString(encryptedData));
|
.encodeToString(encryptedData));
|
||||||
System.out.println("Decrypted Message: " + decryptedMessage);
|
System.out.println("Decrypted Message: " + decryptedMessage);
|
||||||
|
|
||||||
|
|
@ -82,18 +90,26 @@ public final class KeyUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate shared secret using ECDH
|
// Generate shared secret using ECDH
|
||||||
private static SecretKey generateSharedSecret(PrivateKey privateKey,
|
public static SecretKey generateSharedSecret(PrivateKey privateKey,
|
||||||
PublicKey publicKey) throws Exception {
|
PublicKey publicKey) {
|
||||||
|
try {
|
||||||
KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
|
KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH");
|
||||||
keyAgreement.init(privateKey);
|
keyAgreement.init(privateKey);
|
||||||
keyAgreement.doPhase(publicKey, true);
|
keyAgreement.doPhase(publicKey, true);
|
||||||
byte[] sharedSecretBytes = keyAgreement.generateSecret();
|
byte[] sharedSecretBytes = keyAgreement.generateSecret();
|
||||||
return new SecretKeySpec(sharedSecretBytes, 0, 16, "AES");
|
return new SecretKeySpec(sharedSecretBytes, 0, 16, "AES");
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new RuntimeException("Invalid key!", e);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("No such algorithm!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encrypt data using AES-GCM
|
// Encrypt data using AES-GCM
|
||||||
private static byte[] encryptDataWithAESGCM(String data,
|
public static byte[] encryptDataWithAESGCM(String data,
|
||||||
SecretKey sharedSecret) throws Exception {
|
SecretKey sharedSecret) {
|
||||||
|
|
||||||
|
try {
|
||||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||||
|
|
||||||
// Generate random 12-byte IV
|
// Generate random 12-byte IV
|
||||||
|
|
@ -111,11 +127,26 @@ public final class KeyUtils {
|
||||||
System.arraycopy(encryptedData, 0, encryptedDataWithIv, iv.length, encryptedData.length);
|
System.arraycopy(encryptedData, 0, encryptedDataWithIv, iv.length, encryptedData.length);
|
||||||
|
|
||||||
return encryptedDataWithIv;
|
return encryptedDataWithIv;
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("NoSuchAlgorithmException!", e);
|
||||||
|
} catch (NoSuchPaddingException e) {
|
||||||
|
throw new RuntimeException("NoSuchPaddingException!", e);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new RuntimeException("InvalidKeyException!", e);
|
||||||
|
} catch (InvalidAlgorithmParameterException e) {
|
||||||
|
throw new RuntimeException("InvalidAlgorithmParameterException!", e);
|
||||||
|
} catch (IllegalBlockSizeException e) {
|
||||||
|
throw new RuntimeException("IllegalBlockSizeException!", e);
|
||||||
|
} catch (BadPaddingException e) {
|
||||||
|
throw new RuntimeException("BadPaddingException!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt data using AES-GCM
|
// Decrypt data using AES-GCM
|
||||||
private static String decryptDataWithAESGCM(byte[] encryptedDataWithIv,
|
public static String decryptDataWithAESGCM(byte[] encryptedDataWithIv,
|
||||||
SecretKey sharedSecret) throws Exception {
|
SecretKey sharedSecret) {
|
||||||
|
|
||||||
|
try {
|
||||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||||
|
|
||||||
// Extract IV
|
// Extract IV
|
||||||
|
|
@ -130,53 +161,94 @@ public final class KeyUtils {
|
||||||
byte[] decryptedData = cipher.doFinal(encryptedData);
|
byte[] decryptedData = cipher.doFinal(encryptedData);
|
||||||
|
|
||||||
return new String(decryptedData);
|
return new String(decryptedData);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("NoSuchAlgorithmException!", e);
|
||||||
|
} catch (NoSuchPaddingException e) {
|
||||||
|
throw new RuntimeException("NoSuchPaddingException!", e);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new RuntimeException("InvalidKeyException!", e);
|
||||||
|
} catch (InvalidAlgorithmParameterException e) {
|
||||||
|
throw new RuntimeException("InvalidAlgorithmParameterException!", e);
|
||||||
|
} catch (IllegalBlockSizeException e) {
|
||||||
|
throw new RuntimeException("IllegalBlockSizeException!", e);
|
||||||
|
} catch (BadPaddingException e) {
|
||||||
|
throw new RuntimeException("BadPaddingException!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String privateKeyToString(PrivateKey privateKey) {
|
private static String privateKeyToString(PrivateKey privateKey) {
|
||||||
return Base64.getEncoder()
|
return Base64.getUrlEncoder()
|
||||||
.encodeToString(privateKey.getEncoded());
|
.encodeToString(privateKey.getEncoded());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String publicKeyToString(PublicKey publicKey) {
|
private static String publicKeyToString(PublicKey publicKey) {
|
||||||
return Base64.getEncoder()
|
return Base64.getUrlEncoder()
|
||||||
.encodeToString(publicKey.getEncoded());
|
.encodeToString(publicKey.getEncoded());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PrivateKey stringToPrivateKey(String privateKeyStr) throws Exception {
|
public static PrivateKey stringToPrivateKey(String privateKeyStr) {
|
||||||
byte[] keyBytes = Base64.getDecoder()
|
try {
|
||||||
|
byte[] keyBytes = Base64.getUrlDecoder()
|
||||||
.decode(privateKeyStr);
|
.decode(privateKeyStr);
|
||||||
KeyFactory keyFactory = KeyFactory.getInstance("EC");
|
KeyFactory keyFactory = KeyFactory.getInstance("EC");
|
||||||
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
|
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
|
||||||
return keyFactory.generatePrivate(keySpec);
|
return keyFactory.generatePrivate(keySpec);
|
||||||
|
} catch (InvalidKeySpecException e) {
|
||||||
|
throw new RuntimeException("Invalid key!", e);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("No such algorithm!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PublicKey stringToPublicKey(String publicKeyStr) throws Exception {
|
public static PublicKey stringToPublicKey(String publicKeyStr) {
|
||||||
byte[] keyBytes = Base64.getDecoder()
|
try {
|
||||||
|
byte[] keyBytes = Base64.getUrlDecoder()
|
||||||
.decode(publicKeyStr);
|
.decode(publicKeyStr);
|
||||||
KeyFactory keyFactory = KeyFactory.getInstance("EC");
|
KeyFactory keyFactory = KeyFactory.getInstance("EC");
|
||||||
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
|
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
|
||||||
return keyFactory.generatePublic(keySpec);
|
return keyFactory.generatePublic(keySpec);
|
||||||
|
} catch (InvalidKeySpecException e) {
|
||||||
|
throw new RuntimeException("Invalid key!", e);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("No such algorithm!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String signMessage(String message,
|
public static String signMessage(String message,
|
||||||
PrivateKey privateKey) throws Exception {
|
PrivateKey privateKey) {
|
||||||
|
try {
|
||||||
Signature signature = Signature.getInstance("SHA256withECDSA");
|
Signature signature = Signature.getInstance("SHA256withECDSA");
|
||||||
signature.initSign(privateKey);
|
signature.initSign(privateKey);
|
||||||
signature.update(message.getBytes());
|
signature.update(message.getBytes());
|
||||||
byte[] signedBytes = signature.sign();
|
byte[] signedBytes = signature.sign();
|
||||||
return Base64.getEncoder()
|
return Base64.getUrlEncoder()
|
||||||
.encodeToString(signedBytes);
|
.encodeToString(signedBytes);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("NoSuchAlgorithmException!", e);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new RuntimeException("InvalidKeyException!", e);
|
||||||
|
} catch (SignatureException e) {
|
||||||
|
throw new RuntimeException("SignatureException!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the signature
|
// Verify the signature
|
||||||
private static boolean verifySignature(String message,
|
public static boolean verifySignature(String message,
|
||||||
String signatureStr,
|
String signatureStr,
|
||||||
PublicKey publicKey) throws Exception {
|
PublicKey publicKey) {
|
||||||
|
try {
|
||||||
Signature signature = Signature.getInstance("SHA256withECDSA");
|
Signature signature = Signature.getInstance("SHA256withECDSA");
|
||||||
signature.initVerify(publicKey);
|
signature.initVerify(publicKey);
|
||||||
signature.update(message.getBytes());
|
signature.update(message.getBytes());
|
||||||
byte[] signatureBytes = Base64.getDecoder()
|
byte[] signatureBytes = Base64.getUrlDecoder()
|
||||||
.decode(signatureStr);
|
.decode(signatureStr);
|
||||||
return signature.verify(signatureBytes);
|
return signature.verify(signatureBytes);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("NoSuchAlgorithmException!", e);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new RuntimeException("InvalidKeyException!", e);
|
||||||
|
} catch (SignatureException e) {
|
||||||
|
throw new RuntimeException("SignatureException!", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue