package org.thoughtcrime.SMP.crypto.SMP; /* * Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import android.util.Log; import org.spongycastle.util.BigIntegers; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; import java.math.BigInteger; import java.security.PublicKey; import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPublicKey; /** * @author George Politis modified by ludwig on 27/06/15 */ public class SMPOutputStream extends FilterOutputStream implements SerializationConstants { private static final String TAG = SMPOutputStream.class.getSimpleName(); public SMPOutputStream(OutputStream out) { super(out); } private void writeNumber(int value, int length) throws IOException { Log.d(TAG, "writeNumber value: " + value); byte[] b = new byte[length]; for (int i = 0; i < length; i++) { int offset = (b.length - 1 - i) * 8; b[i] = (byte) ((value >>> offset) & 0xFF); } write(b); } public void writeBigInt(BigInteger bi) throws IOException { byte[] b = BigIntegers.asUnsignedByteArray(bi); writeData(b); } public void writeByte(int b) throws IOException { writeNumber(b, TYPE_LEN_BYTE); } public void writeData(byte[] b) throws IOException { int len = (b == null || b.length < 0) ? 0 : b.length; writeNumber(len, DATA_LEN); if (len > 0) write(b); } public void writeInt(int i) throws IOException { writeNumber(i, TYPE_LEN_INT); } public void writeShort(int s) throws IOException { writeNumber(s, TYPE_LEN_SHORT); } /* public void writeMac(byte[] mac) throws IOException { if (mac == null || mac.length != TYPE_LEN_MAC) throw new IllegalArgumentException(); write(mac); } public void writeCtr(byte[] ctr) throws IOException { if (ctr == null || ctr.length < 1) return; int i = 0; while (i < TYPE_LEN_CTR && i < ctr.length) { write(ctr[i]); i++; } } public void writeDHPublicKey(DHPublicKey dhPublicKey) throws IOException { byte[] b = BigIntegers.asUnsignedByteArray(dhPublicKey.getY()); writeData(b); } */ public void writePublicKey(PublicKey pubKey) throws IOException { if (!(pubKey instanceof DSAPublicKey)) throw new UnsupportedOperationException( "Key types other than DSA are not supported at the moment."); DSAPublicKey dsaKey = (DSAPublicKey) pubKey; writeShort(0); DSAParams dsaParams = dsaKey.getParams(); writeBigInt(dsaParams.getP()); writeBigInt(dsaParams.getQ()); writeBigInt(dsaParams.getG()); writeBigInt(dsaKey.getY()); } /* public void writeTlvData(byte[] b) throws IOException { int len = (b == null || b.length < 0) ? 0 : b.length; writeNumber(len, TLV_LEN); if (len > 0) write(b); } public void writeSignature(byte[] signature, PublicKey pubKey) throws IOException { if (!pubKey.getAlgorithm().equals("DSA")) throw new UnsupportedOperationException(); out.write(signature); } public void writeMysteriousX(SignatureX x) throws IOException { writePublicKey(x.longTermPublicKey); writeInt(x.dhKeyID); writeSignature(x.signature, x.longTermPublicKey); } public void writeMysteriousX(SignatureM m) throws IOException { writeBigInt(m.localPubKey.getY()); writeBigInt(m.remotePubKey.getY()); writePublicKey(m.localLongTermPubKey); writeInt(m.keyPairID); } public void writeMysteriousT(MysteriousT t) throws IOException { writeShort(t.protocolVersion); writeByte(t.messageType); if (t.protocolVersion == 3) { writeInt(t.senderInstanceTag); writeInt(t.receiverInstanceTag); } writeByte(t.flags); writeInt(t.senderKeyID); writeInt(t.recipientKeyID); writeDHPublicKey(t.nextDH); writeCtr(t.ctr); writeData(t.encryptedMessage); } */ }