contract Certifications is Ownable {
    using ECDSA for bytes32;
    
    mapping(bytes32 => Certificate) public fingerprints; 
    
    struct Certificate {
        address owner;
        mapping(address => bytes) signatures;
        uint issued;
        uint expires;
        bool exists;
    }
    
    constructor() public {}
    
    /**
    * @dev Certificate a document fingerprint into blockchain
    * @param _fingerprint bytes32. Is the sha3 hash of document. Generated with web3.
    * @param _owner address. The address of who is being certificated. The owner of document.
    * @param _issued uint. The unix miliseconds date of certificate issuing.
    * @param _expires uint. The unix miliseconds date of certificate expiration.
    */
    function addCertificate(
        bytes32 _fingerprint,
        address _owner,
        uint _issued,
        uint _expires
    ) onlyOwner() public returns(bool) {
        require(_issued < _expires, "Issuing date can not be less than expiring date");
        require(_expires > now, "This certificate has already expired");
        require(!fingerprints[_fingerprint].exists, "File has already been certified");
        fingerprints[_fingerprint].owner = _owner;
        fingerprints[_fingerprint].issued = _issued;
        fingerprints[_fingerprint].expires = _expires;
        fingerprints[_fingerprint].exists = true;
        return true;
    }
    
    /**
    * @dev Function to sign a previously generated certificate
    * @param _signer address. The address of who is signing the certificate.
    * @param _fingerprint bytes32. Is the sha3 hash of document. Generated with web3.
    * @param _signature bytes. Signature of the sha3 fingerprint of the file.
    */
    function addSignatureToCertificate(address _signer, bytes32 _fingerprint, bytes memory _signature) onlyOwner() public returns(bool) {
       address signer = _fingerprint.recoverAddress(_signature);
       require(fingerprints[_fingerprint].exists, "Certificate does not exists");
       require(_signer == signer, "Signature does not corresponds to signer");
       fingerprints[_fingerprint].signatures[_signer] = _signature;
       return true;
    }
    
    /**
    * @dev Returns the corresponding signature to a certificate and signer, used to verify signatures
    * @param _signer address. The address of who supposedly signed the certificate.
    * @param _fingerprint bytes32. Is the sha3 hash of document. Generated with web3.
    */
    function getSignature(address _signer, bytes32 _fingerprint) public view returns(bytes memory) {
        return fingerprints[_fingerprint].signatures[_signer];
    }
}
function getSignature(address _signer, bytes32 _fingerprint) public view returns(bytes memory) {
    return fingerprints[_fingerprint].signatures[_signer];
}

/**
 * @dev Returns the corresponding signature to a certificate and signer, used to verify signatures
 * @param _signer address. The address of who supposedly signed the certificate.
 * @param _fingerprint bytes32. Is the sha3 hash of document. Generated with web3.
 */