October 19, 2016

Python Script for Generating, Copying and Sending by email an SSH Login Keys for (PuTTY and GIT)


1. Prerequisites

1. Download and Install GIT Link

2. Download and Install Python 2.7.3 Link

3. Download PuTTy Link

4. Download WinSCP Link


2. Writing Scripts

1. Create Directory that will be your workspace (i.e. c:\ssh-scripts\)

2. Copy WinSCP.exe to your workspace directory

3. Create new script file in your workspace and name it "gen-ssh-key.py"

4. The script file will look like this:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
from optparse import OptionParser
import subprocess, os, sys, getopt, shutil
import os.path

import smtplib
# For guessing MIME type based on file name extension
import mimetypes
from email import encoders
from email.message import Message
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

##########################
sender = "ibrahim.sawalha@gmail.com"
COMMASPACE = ', '
copyMessage = "\n\n"
##########################

##### Example
# python gen-ssh-key.py --generate --copy --userid ibrahim.sawalha --serverIp thin:10.100.102.37

parser = OptionParser()
parser.add_option("-i", "--userid", dest="userid", help="The User ID", metavar="USER_ID")

parser.add_option("-s", "--serverIp", dest="serverIp", help="Servers IP Addresses sperated by comma ,")
parser.add_option("-u", "--serverUser", dest="serverUser", help="Servers Username [default: thin]")

parser.add_option("-g", "--generate", dest="generate", help="Generate Public and Private Keys", action="store_true", default=False)
parser.add_option("-c", "--copy", dest="copy", help="Copy Public Key to Server", action="store_true", default=False)

(options, args) = parser.parse_args()

if (options.generate == False and options.copy == False):
 parser.error("[ERROR] One or Booth arguments should be provided --generate and --copy")

if (options.copy == True):
 if (options.serverIp == None):
  parser.error("[ERROR] When using --copy you should provide --serverIp value")

if (options.userid == None):
   parser.error("[ERROR] User ID was not specified, use --userid USER_ID")

userid = options.userid
emailAddress = userid + '@gmail.com'
directory = userid
recipients = sender + "," + emailAddress

#if not  os.path.exists(directory):
# os.makedirs(directory)
keyFile = directory + '/' + userid + '-key'

#### Generate Public/Private Keys
if (options.generate == True):
    print 'User ID .........' , userid
    print 'Email Address ...' , emailAddress
    user_input = ""
    print '============================================================'
    print '[WARN] You are going to geneate NEW public/private keys.'

    if os.path.exists(directory):
        print '[ERROR] Directory ' + directory + ' already exist, please delete it before continue.'
        exit(1)
    os.makedirs(directory)
    while (user_input not in ['yes','no']):
        user_input = raw_input("Are you sure you want to continue? yes/no: ")
        if user_input == 'yes':
            print 'ssh-keygen -t rsa -b 1024 -f ' + keyFile + ' -P \"\" -C ' + emailAddress
            os.system('ssh-keygen -t rsa -b 1024 -f ' + keyFile + ' -P \"\" -C ' + emailAddress)

            print 'Converting ssh private key to PuTTY format .ppk'
            print 'winscp.exe /keygen ' + keyFile + ' /output=' + keyFile + '.ppk'
            os.system('winscp.exe /keygen ' + keyFile + ' /output=' + keyFile + '.ppk')
        if user_input == 'no':
            print "[INFO] Private/Public key will not be generated."

#### Copy Public Key to Server
if (options.copy == True):
    if not os.path.exists(directory):
        print '[ERROR] Directory ' + directory + ' does not exist.'
        exit(1)
    serverIp = options.serverIp 
    #serverUser = "thin"
    #if (options.serverUser != None):
    #    serverUser = options.serverUser
    if not os.path.isfile(keyFile):
        print '[ERROR] File <' + keyFile + '> was not found.'
        exit(1)
    serversIp = serverIp.strip().split(",")
    for ip in serversIp:
        tmp=ip.split(':')
        linux_user=tmp[0]
        linux_ip=tmp[1]
        print 'cat '+ keyFile + '.pub | ssh ' + linux_user + '@' + linux_ip + ' \"mkdir -p ~/.ssh && cat >>  ~/.ssh/authorized_keys\"'
        print '=== Start Copy to Server ==='
        os.system('cat '+ keyFile + '.pub | ssh ' + linux_user + '@' + linux_ip + ' \"mkdir -p ~/.ssh && cat >>  ~/.ssh/authorized_keys\"')
        print '=== End Copy to Server ==='
        copyMessage += "You can use your private key to connect to : " + linux_ip + " server.\n"

print '==================================================='
print 'Convert SSH Keys to PPK Format'
print 'https://kb.site5.com/shell-access-ssh/how-to-convert-ssh-keys-to-ppk-format/'
print '[NOTE] You must convert the SSH Private Key Format to Putty Format .pkk to use this key within Putty Application'

outer = MIMEMultipart()
outer['Subject'] = 'Private & Public Keys'
outer['To'] = emailAddress
outer['From'] = sender
outer['CC'] = sender

copyMessage += '\nAttached files as follows:\n'

for filename in os.listdir(directory):
    if filename.endswith('.ppk'):
        copyMessage += filename + '\tPutty Private Key Format used with Putty.\n'
    elif filename.endswith('.pub'):
        copyMessage += filename + '\tStandard SSH Public Key.\n'
    elif not filename.endswith('.pub') and not filename.endswith('.ppk'):
        copyMessage += userid + '\t\tStandard SSH Private Key used with Linux.\n'
    else:
        copyMessage += userid + '\t\tIdon\'t know \n'
copyMessage += "\nImportant Note:\nYou must save and backup the attached files in your PC.\n"

msgText = MIMEText('Dear ' + userid + ", \nAttached files are your private and public keys that will be used for connecting to Linux servers."+copyMessage)
outer.attach(msgText)

for filename in os.listdir(directory):
    path = os.path.join(directory, filename)
    
    if not os.path.isfile(path):
        continue
    ctype, encoding = mimetypes.guess_type(path)
    if ctype is None or encoding is not None:
        ctype = 'application/octet-stream'

    maintype, subtype = ctype.split('/', 1)
    if maintype == 'text':
        fp = open(path)
        # Note: we should handle calculating the charset
        msg = MIMEText(fp.read(), _subtype=subtype)
        fp.close()
    elif maintype == 'image':
        fp = open(path, 'rb')
        msg = MIMEImage(fp.read(), _subtype=subtype)
        fp.close()
    elif maintype == 'audio':
        fp = open(path, 'rb')
        msg = MIMEAudio(fp.read(), _subtype=subtype)
        fp.close()
    else:
        fp = open(path, 'rb')
        msg = MIMEBase(maintype, subtype)
        msg.set_payload(fp.read())
        fp.close()
        # Encode the payload using Base64
        encoders.encode_base64(msg)
    # Set the filename parameter
    msg.add_header('Content-Disposition', 'attachment', filename=filename)
    outer.attach(msg)
# Now send or store the message

composed = outer.as_string()
#s = smtplib.SMTP('100.100.20.1','25')
s = smtplib.SMTP('smtp.gmail.com:587')
s.starttls()
s.login('user-id@gmail.com', 'password')
s.helo('icslondon.com')
s.sendmail(sender, emailAddress, composed)
s.quit()

print 'Finish==================================================='

3. How to use this script

This script its main target is to Generate an SSH private and public key then it will convert the private key to PuTTY formatted key to be used with PuTTY for connection.
Then the script will copy the public key to the Linux server as entered.
Also the generated keys are saved in directory named by the entered user ID "check --userid argument". After that the script will creates and email and attach these three keys to it and send it the user's email address (i.e. ibrahim.sawalha@gmail.com).

Examples of execution:
1. I want to generate NEW keys and copy them to server 10.100.102.37 and this machine's login user is thin, also the user's email address is ibrahim.sawalha@gmail.com

1
python gen-ssh-key.py --generate --copy --userid ibrahim.sawalha --serverIp thin:10.100.102.37

2. I want to generate NEW keys without copying them using the user's email address is ibrahim.sawalha@icsfs.com
1
python gen-ssh-key.py --generate --userid ibrahim.sawalha 

Simple Java AES With Padding encrypt/decrypt example

Hope this will be useful to you all.
NOTE: To compile you need additional Apache Commons Codec jar, which is available here: http://commons.apache.org/proper/commons-codec/download_codec.cgi


AESCryptoPaddingUtils Class

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

public class AESCryptoPaddingUtils {

    public synchronized static void encryptFile(String password, String initVector, File inputFile, File outputFile)
            throws Exception {
        FileInputStream inputStream = new FileInputStream(inputFile);
        byte[] inputBytes = new byte[(int) inputFile.length()];
        inputStream.read(inputBytes);

        byte[] outputBytes = encryptBytes(password, initVector, inputBytes);

        FileOutputStream outputStream = new FileOutputStream(outputFile);
        outputStream.write(outputBytes);

        inputStream.close();
        outputStream.close();
    }

    public synchronized static void decryptFile(String password, String initVector, File inputFile, File outputFile)
            throws Exception {
        FileInputStream inputStream = new FileInputStream(inputFile);
        byte[] inputBytes = new byte[(int) inputFile.length()];
        inputStream.read(inputBytes);

        byte[] outputBytes = decryptBytes(password, initVector, inputBytes);

        FileOutputStream outputStream = new FileOutputStream(outputFile);
        outputStream.write(outputBytes);

        inputStream.close();
        outputStream.close();
    }

    ////////////
    public synchronized static byte[] encryptBytes(String key, String initVector, byte[] value) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(value);
            return encrypted;
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public synchronized static String encryptString(String key, String initVector, String value)
            throws UnsupportedEncodingException {
        return Base64.encodeBase64String(encryptBytes(key, initVector, value.getBytes("UTF-8")));
    }

    public synchronized static byte[] decryptBytes(String key, String initVector, byte[] encrypted) {
        try {
            IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            return cipher.doFinal(encrypted);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    public synchronized static String decryptString(String key, String initVector, String encrypted)
            throws UnsupportedEncodingException {
        return new String(decryptBytes(key, initVector, Base64.decodeBase64(encrypted)));
    }

    ///////////////////////////////

    public static void main(String[] args) throws Exception {
        String password = "1234567891234567"; // 16 char == 128 bit
        String initVector = "RandomInitVector"; // 16 bytes IV

        // 1
        String encrypted = AESCryptoPaddingUtils.encryptString(password, initVector, "Ibrahim Adnan Ibrahim Sawalha");
        System.out.println(encrypted);
        String decrypted = AESCryptoPaddingUtils.decryptString(password, initVector, encrypted);
        System.out.println(decrypted);

        // 2
        byte[] encryptedBytes = AESCryptoPaddingUtils.encryptBytes(password, initVector,
            "Ibrahim Adnan Ibrahim Sawalha".getBytes("UTF-8"));
        System.out.println(Base64.encodeBase64String(encryptedBytes));
        byte[] decryptedBytes = AESCryptoPaddingUtils.decryptBytes(password, initVector, encryptedBytes);
        System.out.println(new String(decryptedBytes));

        // 3
        File inputFile = new File("document.mp4");
        File encryptedFile = new File("document.encrypted.mp4");
        File decryptedFile = new File("document.decrypted.mp4");

        try {
            AESCryptoPaddingUtils.encryptFile(password, initVector, inputFile, encryptedFile);
            AESCryptoPaddingUtils.decryptFile(password, initVector, encryptedFile, decryptedFile);
        } catch (AESCryptoException ex) {
            System.out.println(ex.getMessage());
            ex.printStackTrace();
        }
    }
}

Simple Java AES encrypt/decrypt example

Hope this will be useful to you all.

AESCryptoUtils Class

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

public class AESCryptoUtils {

    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES";

    public synchronized static void encrypt(String key, File inputFile, File outputFile) throws AESCryptoException {
        doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile);
    }

    public synchronized static void decrypt(String key, File inputFile, File outputFile) throws AESCryptoException {
        doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile);
    }

    private synchronized static void doCrypto(int cipherMode, String key, File inputFile, File outputFile)
            throws AESCryptoException {
        try {
            Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(cipherMode, secretKey);

            FileInputStream inputStream = new FileInputStream(inputFile);
            byte[] inputBytes = new byte[(int) inputFile.length()];
            inputStream.read(inputBytes);

            byte[] outputBytes = cipher.doFinal(inputBytes);

            FileOutputStream outputStream = new FileOutputStream(outputFile);
            outputStream.write(outputBytes);

            inputStream.close();
            outputStream.close();

        } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | BadPaddingException
                | IllegalBlockSizeException | IOException ex) {
            throw new AESCryptoException("Error encrypting/decrypting file", ex);
        }
    }

    public static void main(String[] args) {
        // String key = "Bar12345Bar12345"; 128 bit key
        String key = "ibrahimsawalah12";

        System.out.println(key.length());
        if (key.length() != 16) {
            System.err.println("Key must contains 16 character.");
            System.exit(1);
        }
        File inputFile = new File("document.mp4");
        File encryptedFile = new File("document.encrypted.mp4");
        File decryptedFile = new File("document.decrypted.mp4");

        try {
            encrypt(key, inputFile, encryptedFile);
            decrypt(key, encryptedFile, decryptedFile);
        } catch (AESCryptoException ex) {
            System.out.println(ex.getMessage());
            ex.printStackTrace();
        }
    }
}

AESCryptoException Class

public class AESCryptoException extends Exception {

    private static final long serialVersionUID = 8455563779756237115L;

    public AESCryptoException() {
    }

    public AESCryptoException(String message, Throwable throwable) {
        super(message, throwable);
    }
}