/*
* Kontalk Android client
* Copyright (C) 2017 Kontalk Devteam <devteam@kontalk.org>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.kontalk.crypto;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Generic coder interface.
* @author Daniele Ricci
*/
public abstract class Coder {
/*
* Security flags for encryption features.
* These flags marks only features found in a message.
*/
/** Cleartext messages. Not encrypted nor signed. */
public static final int SECURITY_CLEARTEXT = 0;
/** Legacy (2.x) encryption method. For compatibility with old messages. */
public static final int SECURITY_LEGACY_ENCRYPTED = 1;
/** Basic encryption (e.g. PGP encrypted). Safe enough. */
public static final int SECURITY_BASIC_ENCRYPTED = 1 << 1;
/** Basic signature found (e.g. PGP signature). Safe enough. */
public static final int SECURITY_BASIC_SIGNED = 1 << 2;
/** Advanced encryption (e.g. OTR). Very strong. */
public static final int SECURITY_ADVANCED_ENCRYPTED = 1 << 3;
/** Advanced signature found (e.g. OTR). Very strong. */
public static final int SECURITY_ADVANCED_SIGNED = 1 << 4;
/*
* Security flags for encryption status.
* These flags, together with the ones above, help clarifying whether the
* security features found in a message are verified and safe.
*/
/** Digital signature verification failed. */
public static final int SECURITY_ERROR_INVALID_SIGNATURE = 1 << 16;
/** Invalid sender. */
public static final int SECURITY_ERROR_INVALID_SENDER = 1 << 17;
/** Invalid recipient. */
public static final int SECURITY_ERROR_INVALID_RECIPIENT = 1 << 18;
/** Invalid timestamp. */
public static final int SECURITY_ERROR_INVALID_TIMESTAMP = 1 << 19;
/** Invalid packet data or message parsing failed. */
public static final int SECURITY_ERROR_INVALID_DATA = 1 << 20;
/** Decryption failed. */
public static final int SECURITY_ERROR_DECRYPT_FAILED = 1 << 21;
/** Data integrity check failed. */
public static final int SECURITY_ERROR_INTEGRITY_CHECK = 1 << 22;
/** User's public key not available (for encryption and/or verification). */
public static final int SECURITY_ERROR_PUBLIC_KEY_UNAVAILABLE = 1 << 23;
/* Quick flags combinations. */
/** Basic encryption (e.g. PGP). */
public static final int SECURITY_BASIC = SECURITY_BASIC_ENCRYPTED | SECURITY_BASIC_SIGNED;
/** How much time to consider a message timestamp drifted (and thus compromised). */
public static final long TIMEDIFF_THRESHOLD = TimeUnit.DAYS.toMillis(1);
/** Encrypts a string. */
public abstract byte[] encryptText(CharSequence text) throws GeneralSecurityException;
/** Encrypts a stanza. */
public abstract byte[] encryptStanza(CharSequence xml) throws GeneralSecurityException;
/** Decrypts a byte array which should contain text. */
public abstract DecryptOutput decryptText(byte[] encrypted, boolean verify)
throws GeneralSecurityException;
/** Encrypts a file. */
public abstract void encryptFile(InputStream input, OutputStream output) throws GeneralSecurityException;
/** Decrypts a file. */
public abstract void decryptFile(InputStream input, boolean verify,
OutputStream output, List<DecryptException> errors) throws GeneralSecurityException;
/** Verifies a byte array which should contain text. */
public abstract Coder.VerifyOutput verifyText(byte[] signed, boolean verify) throws GeneralSecurityException;
/** Returns true if the given security flags has some error bit on. */
public static boolean isError(int securityFlags) {
return (securityFlags & SECURITY_ERROR_INVALID_SIGNATURE) != 0 ||
(securityFlags & SECURITY_ERROR_INVALID_SENDER) != 0 ||
(securityFlags & SECURITY_ERROR_INVALID_RECIPIENT) != 0 ||
(securityFlags & SECURITY_ERROR_INVALID_TIMESTAMP) != 0 ||
(securityFlags & SECURITY_ERROR_INVALID_DATA) != 0 ||
(securityFlags & SECURITY_ERROR_DECRYPT_FAILED) != 0 ||
(securityFlags & SECURITY_ERROR_INTEGRITY_CHECK) != 0 ||
(securityFlags & SECURITY_ERROR_PUBLIC_KEY_UNAVAILABLE) != 0;
}
public static class DecryptOutput {
public final String mime;
public final String cleartext;
public final Date timestamp;
public final List<DecryptException> errors;
DecryptOutput(String cleartext, String mime, Date timestamp, List<DecryptException> errors) {
this.cleartext = cleartext;
this.mime = mime;
this.timestamp = timestamp;
this.errors = errors;
}
}
public static class VerifyOutput {
public final String cleartext;
public final Date timestamp;
public final List<VerifyException> errors;
VerifyOutput(String cleartext, Date timestamp, List<VerifyException> errors) {
this.cleartext = cleartext;
this.timestamp = timestamp;
this.errors = errors;
}
}
}