package org.ourfilesystem.simulator.security;

/*
OurFileSystem is a peer2peer file sharing program.
Copyright (C) 2012  Robert Gass

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 2 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

*/

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

import org.ourfilesystem.db.Peer;
import org.ourfilesystem.db.Post;
import org.ourfilesystem.security.CryptoDataBaseInterface;
import org.ourfilesystem.security.KeySet;
import org.ourfilesystem.security.PublicKeySet;
import org.ourfilesystem.security.PublicKeySetSigned;
import org.ourfilesystem.security.SignedDigest;
import org.ourfilesystem.utilities.FileUtils;

public class CryptoDataBaseImpl implements CryptoDataBaseInterface {
	
	public long ID;
	
	public CryptoDataBaseImpl(long id) {
		ID = id;
	}

	@Override
	public KeySet generateNewKeys() {
		KeySet ks = new KeySet();
		PublicKeySet pub = new PublicKeySet();
		pub.setPublicEncryptionKey(ID);
		pub.setPublicSigningKey(ID);
		ks.setPublicKeySet(pub);
		ks.setPrivateEncryptionKey(ID);
		ks.setPrivateSigningKey(ID);
		return ks;
	}

	@Override
	public boolean verifyPeer(PublicKeySetSigned pubsigned, Object pub) {
		long dig = (Long)pubsigned.getPublicEncryptionKey();
		if (dig != (Long)pubsigned.getSignature().getDigest()) { return false; }
		long sid = (Long)pubsigned.getSignature().getSignature();
		return sid == ((dig * 0x10000L) + (Long)pub);
	}

	@Override
	public Peer signPeer(Peer p, Object peerid, Object privkey) {
		PublicKeySetSigned pubsigned = p.getPeerKeysAndIdentity();
		SignedDigest sg = new SignedDigest();
		long dig = (Long)p.getPeerKeysAndIdentity().getPublicEncryptionKey();
		sg.setDigest(dig);
		sg.setPeerIdentifier(peerid);
		long id = (Long)privkey;
		sg.setSignature(((dig * 0x10000L) + id));
		pubsigned.setSignature(sg);
		return p;
	}

	@Override
	public boolean digEquals(Object id0, Object id1) {
		long lid0 = (Long)id0;
		long lid1 = (Long)id1;
		return lid0 == lid1;
	}

	@Override
	public boolean verifyPost(Post p, Object pubkey) {
		SignedDigest sg = p.getSignedDigest();
		long dig = (Long)sg.getDigest();
		if (p.getPostNumber() == dig) {
			long sig = (Long)sg.getSignature();
			return sig == ((dig * 0x10000L) + (Long)pubkey);
		}
		return false;
	}

	@Override
	public Post signPost(Post p, Object peerid, Object privkey) {
		long dig = p.getPostNumber();
		long id = (Long)privkey;
		SignedDigest sg = new SignedDigest();
		sg.setDigest(dig);
		sg.setPeerIdentifier(peerid);
		sg.setSignature(((dig * 0x10000L) + id));
		p.setSignedDigest(sg);
		return p;
	}

	@Override
	public Object digestFile(File f) {
		try {
			FileInputStream fis = new FileInputStream(f);
			byte b[] = new byte[Long.SIZE/Byte.SIZE];
			FileUtils.fillBytes(b, fis);
			fis.close();
			ByteBuffer buf = ByteBuffer.wrap(b);
			return buf.getLong();
		}
		catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public void selfSignMyPeerId(Peer p, Object privkey) {
		PublicKeySetSigned pubsigned = p.getPeerKeysAndIdentity();
		SignedDigest sg = new SignedDigest();
		long dig = (Long)p.getPeerKeysAndIdentity().getPublicEncryptionKey();
		sg.setDigest(dig);
		sg.setPeerIdentifier(dig);
		long id = (Long)privkey;
		sg.setSignature(((dig * 0x10000L) + id));
		pubsigned.setSignature(sg);		
	}

	@Override
	public void signLocation(Peer p, Object privkey) {
		SignedDigest sg = new SignedDigest();
		long dig = (Long)p.getLocation();
		sg.setDigest(dig);
		sg.setPeerIdentifier(null);
		long id = (Long)privkey;
		sg.setSignature(((dig * 0x10000L) + id));
		p.setLocationSignature(sg);
	}

	@Override
	public boolean verifyLocation(Peer p, Object pub) {
		SignedDigest sg = p.getLocationSignature();
		if (sg == null) {
			return false;
		}
		long id = (Long)pub;
		if (p.getLocation() == null) {
			return false;
		}
		if (sg.getDigest() == null) {
			return false;
		}
		if (!p.getLocation().equals(sg.getDigest())) {
			return false;
		}
		long dig = (Long)sg.getDigest();
		if (!sg.getSignature().equals((dig * 0x10000L) + id)) {
			return false;
		}
		return true;
	}

}
