|
|
@ -66,6 +66,8 @@ import org.apache.commons.compress.archivers.ArchiveInputStream;
|
|
|
|
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
|
|
|
|
import org.apache.commons.compress.archivers.ArchiveStreamFactory;
|
|
|
|
import org.apache.commons.compress.archivers.zip.UnsupportedZipFeatureException;
|
|
|
|
import org.apache.commons.compress.archivers.zip.UnsupportedZipFeatureException;
|
|
|
|
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
|
|
|
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
|
|
|
|
|
|
|
|
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
|
|
|
|
|
|
|
|
import org.bouncycastle.crypto.signers.Ed25519Signer;
|
|
|
|
import org.json.JSONObject;
|
|
|
|
import org.json.JSONObject;
|
|
|
|
import org.jsoup.nodes.Document;
|
|
|
|
import org.jsoup.nodes.Document;
|
|
|
|
import org.jsoup.nodes.Element;
|
|
|
|
import org.jsoup.nodes.Element;
|
|
|
@ -2453,35 +2455,46 @@ public class MessageHelper {
|
|
|
|
String p = pubkey.replaceAll("\\s+", "");
|
|
|
|
String p = pubkey.replaceAll("\\s+", "");
|
|
|
|
Log.i("DKIM pubkey=" + p);
|
|
|
|
Log.i("DKIM pubkey=" + p);
|
|
|
|
|
|
|
|
|
|
|
|
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(Base64.decode(p, Base64.DEFAULT));
|
|
|
|
|
|
|
|
KeyFactory keyFactory = KeyFactory.getInstance("Ed25519".equals(salgo) ? "Ed25519" : "RSA");
|
|
|
|
|
|
|
|
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
|
|
|
|
|
|
|
|
Signature sig = Signature.getInstance(salgo); // a=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// https://stackoverflow.com/a/43984402/1794097
|
|
|
|
|
|
|
|
if (pubKey instanceof RSAPublicKey)
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
int keylen = ((RSAPublicKey) pubKey).getModulus().bitLength();
|
|
|
|
|
|
|
|
Log.i("DKIM RSA pubkey length=" + keylen);
|
|
|
|
|
|
|
|
if (keylen < DKIM_MIN_KEY_LENGTH)
|
|
|
|
|
|
|
|
throw new IllegalArgumentException("RSA pubkey length " + keylen + " < " + DKIM_MIN_KEY_LENGTH);
|
|
|
|
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
|
|
|
|
Log.e(ex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String hash = kv.get("b");
|
|
|
|
String hash = kv.get("b");
|
|
|
|
if (hash == null)
|
|
|
|
if (hash == null)
|
|
|
|
return null;
|
|
|
|
return null;
|
|
|
|
String s = hash.replaceAll("\\s+", "");
|
|
|
|
String s = hash.replaceAll("\\s+", "");
|
|
|
|
Log.i("DKIM signature=" + s);
|
|
|
|
Log.i("DKIM signature=" + s);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
byte[] data = head.toString().getBytes();
|
|
|
|
|
|
|
|
byte[] key = Base64.decode(p, Base64.DEFAULT);
|
|
|
|
byte[] signature = Base64.decode(s, Base64.DEFAULT);
|
|
|
|
byte[] signature = Base64.decode(s, Base64.DEFAULT);
|
|
|
|
|
|
|
|
|
|
|
|
sig.initVerify(pubKey);
|
|
|
|
boolean verified;
|
|
|
|
sig.update(head.toString().getBytes());
|
|
|
|
if ("Ed25519".equals(salgo)) {
|
|
|
|
|
|
|
|
Ed25519Signer verifier = new Ed25519Signer();
|
|
|
|
|
|
|
|
verifier.init(false, new Ed25519PublicKeyParameters(key));
|
|
|
|
|
|
|
|
verifier.update(data, 0, data.length);
|
|
|
|
|
|
|
|
verified = verifier.verifySignature(signature);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(key);
|
|
|
|
|
|
|
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
|
|
|
|
|
|
|
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
|
|
|
|
|
|
|
|
Signature sig = Signature.getInstance(salgo); // a=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// https://stackoverflow.com/a/43984402/1794097
|
|
|
|
|
|
|
|
if (pubKey instanceof RSAPublicKey)
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
int keylen = ((RSAPublicKey) pubKey).getModulus().bitLength();
|
|
|
|
|
|
|
|
Log.i("DKIM RSA pubkey length=" + keylen);
|
|
|
|
|
|
|
|
if (keylen < DKIM_MIN_KEY_LENGTH)
|
|
|
|
|
|
|
|
throw new IllegalArgumentException("RSA pubkey length " + keylen + " < " + DKIM_MIN_KEY_LENGTH);
|
|
|
|
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
|
|
|
|
Log.e(ex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sig.initVerify(pubKey);
|
|
|
|
|
|
|
|
sig.update(data);
|
|
|
|
|
|
|
|
verified = sig.verify(signature);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
boolean verified = sig.verify(signature);
|
|
|
|
|
|
|
|
Log.i("DKIM valid=" + verified +
|
|
|
|
Log.i("DKIM valid=" + verified +
|
|
|
|
|
|
|
|
" algo=" + salgo +
|
|
|
|
" dns=" + dns +
|
|
|
|
" dns=" + dns +
|
|
|
|
" from=" + formatAddresses(getFrom()));
|
|
|
|
" from=" + formatAddresses(getFrom()));
|
|
|
|
|
|
|
|
|
|
|
|