WIP
diff --git a/.idea/markdown-navigator.xml b/.idea/markdown-navigator.xml
deleted file mode 100644
index 7753d6d..0000000
--- a/.idea/markdown-navigator.xml
+++ /dev/null
@@ -1,78 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="MarkdownProjectSettings" wasCopied="true">
-    <PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true" openRemoteLinks="true" replaceUnicodeEmoji="false" lastLayoutSetsDefault="false">
-      <PanelProvider>
-        <provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
-      </PanelProvider>
-    </PreviewSettings>
-    <ParserSettings gitHubSyntaxChange="false" emojiShortcuts="1" emojiImages="0">
-      <PegdownExtensions>
-        <option name="ABBREVIATIONS" value="false" />
-        <option name="ANCHORLINKS" value="true" />
-        <option name="ASIDE" value="false" />
-        <option name="ATXHEADERSPACE" value="true" />
-        <option name="AUTOLINKS" value="true" />
-        <option name="DEFINITIONS" value="false" />
-        <option name="DEFINITION_BREAK_DOUBLE_BLANK_LINE" value="false" />
-        <option name="FENCED_CODE_BLOCKS" value="true" />
-        <option name="FOOTNOTES" value="false" />
-        <option name="HARDWRAPS" value="false" />
-        <option name="HTML_DEEP_PARSER" value="false" />
-        <option name="INSERTED" value="false" />
-        <option name="QUOTES" value="false" />
-        <option name="RELAXEDHRULES" value="true" />
-        <option name="SMARTS" value="false" />
-        <option name="STRIKETHROUGH" value="true" />
-        <option name="SUBSCRIPT" value="false" />
-        <option name="SUPERSCRIPT" value="false" />
-        <option name="SUPPRESS_HTML_BLOCKS" value="false" />
-        <option name="SUPPRESS_INLINE_HTML" value="false" />
-        <option name="TABLES" value="true" />
-        <option name="TASKLISTITEMS" value="true" />
-        <option name="TOC" value="false" />
-        <option name="WIKILINKS" value="true" />
-      </PegdownExtensions>
-      <ParserOptions>
-        <option name="ADMONITION_EXT" value="false" />
-        <option name="ATTRIBUTES_EXT" value="false" />
-        <option name="COMMONMARK_LISTS" value="true" />
-        <option name="DUMMY" value="false" />
-        <option name="EMOJI_SHORTCUTS" value="true" />
-        <option name="ENUMERATED_REFERENCES_EXT" value="false" />
-        <option name="FLEXMARK_FRONT_MATTER" value="false" />
-        <option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" />
-        <option name="GFM_TABLE_RENDERING" value="true" />
-        <option name="GITBOOK_URL_ENCODING" value="false" />
-        <option name="GITHUB_LISTS" value="false" />
-        <option name="GITHUB_WIKI_LINKS" value="true" />
-        <option name="HEADER_ID_NO_DUPED_DASHES" value="false" />
-        <option name="JEKYLL_FRONT_MATTER" value="false" />
-        <option name="NO_TEXT_ATTRIBUTES" value="false" />
-        <option name="PARSE_HTML_ANCHOR_ID" value="false" />
-        <option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
-      </ParserOptions>
-    </ParserSettings>
-    <HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true" embedImages="false" embedHttpImages="false" imageUriSerials="false">
-      <GeneratorProvider>
-        <provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
-      </GeneratorProvider>
-      <headerTop />
-      <headerBottom />
-      <bodyTop />
-      <bodyBottom />
-    </HtmlSettings>
-    <CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssUriSerial="false" isCssTextEnabled="false" isDynamicPageWidth="true">
-      <StylesheetProvider>
-        <provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" />
-      </StylesheetProvider>
-      <ScriptProviders />
-      <cssText />
-      <cssUriHistory />
-    </CssSettings>
-    <HtmlExportSettings updateOnSave="false" parentDir="" targetDir="" cssDir="" scriptDir="" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetExt="" useTargetExt="false" noCssNoScripts="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" linkFormatType="HTTP_ABSOLUTE" />
-    <LinkMapSettings>
-      <textMaps />
-    </LinkMapSettings>
-  </component>
-</project>
\ No newline at end of file
diff --git a/.idea/markdown-navigator/profiles_settings.xml b/.idea/markdown-navigator/profiles_settings.xml
deleted file mode 100644
index 57927c5..0000000
--- a/.idea/markdown-navigator/profiles_settings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<component name="MarkdownNavigator.ProfileManager">
-  <settings default="" pdf-export="" />
-</component>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 35eb1dd..94a25f7 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="VcsDirectoryMappings">
-    <mapping directory="" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
   </component>
 </project>
\ No newline at end of file
diff --git a/.stutter/java8.lock b/.stutter/java8.lock
index 563a834..9559841 100644
--- a/.stutter/java8.lock
+++ b/.stutter/java8.lock
@@ -1,33 +1,3 @@
 # DO NOT MODIFY: Generated by Stutter plugin.
-2.10
-2.11
-2.12
-2.13
-2.14
-2.14.1
-3.0
-3.1
-3.2
-3.2.1
-3.3
-3.4
-3.4.1
-3.5
-3.5.1
-4.0
-4.0.1
-4.0.2
-4.1
-4.2
-4.2.1
 4.3
-4.3.1
-4.4
-4.4.1
-4.5
-4.5.1
-4.6
-4.7
-4.8
-4.8.1
 4.9
diff --git a/.stutter/java9.lock b/.stutter/java9.lock
index 563a834..9559841 100644
--- a/.stutter/java9.lock
+++ b/.stutter/java9.lock
@@ -1,33 +1,3 @@
 # DO NOT MODIFY: Generated by Stutter plugin.
-2.10
-2.11
-2.12
-2.13
-2.14
-2.14.1
-3.0
-3.1
-3.2
-3.2.1
-3.3
-3.4
-3.4.1
-3.5
-3.5.1
-4.0
-4.0.1
-4.0.2
-4.1
-4.2
-4.2.1
 4.3
-4.3.1
-4.4
-4.4.1
-4.5
-4.5.1
-4.6
-4.7
-4.8
-4.8.1
 4.9
diff --git a/README.md b/README.md
index 633b83b..8148402 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,37 @@
 gradle-keygen-plugin
 ====================
 
+This plugin provides Gradle ability to generate SSH keys.
+
+Usage:
+```
+plugins {
+    id 'org.fidata.keygen'
+}
+
+keygen {
+    keyType = RSA
+    keySize = 4096
+}
+
+task('generateSSHKey', type: GenerateSSHKeyTask) {
+    privateKeyFile = layout.buildDirectory.file('ssh_key')
+    email = 'test@example.com'
+}
+```
+
+This task, when run, would produce `ssh_key` and `ssh_key.pub` files
+in `build` directory.
+
+`keyType` and `keySize` properties can be set per-task via its properties.
+Otherwise, project-wide values from `keygen` extension are used.
+
+
+
+
+
+Other types of keys could be supported in the future.
+
 
 ------------------------------------------------------------------------
 Copyright © 2018  Basil Peace
diff --git a/build.gradle b/build.gradle
index bf562dc..d14bdd0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -24,8 +24,17 @@
 
 description = 'Provides Keygen task to Gradle' // TODO
 
+license = 'Apache-2.0'
 publicReleases = true
 
+contacts {
+  'grv87@yandex.ru' {
+    moniker 'Basil Peace'
+    github 'grv87'
+    roles 'owner', 'developer'
+  }
+}
+
 dependencies {
   implementation 'com.jcraft:jsch:0.1.54'
 }
@@ -40,19 +49,20 @@
 }
 
 dependencies {
-  // compatTestImplementation group: 'commons-io', name: 'commons-io', version: 'latest.release'
+  compatTestImplementation group: 'commons-io', name: 'commons-io', version: 'latest.release'
 }
 
 stutter {
+  sparse = true
   java(8) {
-    compatibleRange '2.10'
+    compatibleRange '4.3'
   }
   java(9) {
-    compatibleRange '2.10'
+    compatibleRange '4.3'
   }
 }
 
-// tasks.codenarcCompatTest.disabledRules.add 'JavaIoPackageAccess'
+tasks.codenarcCompatTest.disabledRules.add 'JavaIoPackageAccess'
 
 pluginBundle.plugins {
   keygenPlugin {
diff --git a/gradle/dependency-locks/compatTestCompileClasspath.lockfile b/gradle/dependency-locks/compatTestCompileClasspath.lockfile
index 03861dc..23a1524 100644
--- a/gradle/dependency-locks/compatTestCompileClasspath.lockfile
+++ b/gradle/dependency-locks/compatTestCompileClasspath.lockfile
@@ -2,6 +2,7 @@
 # Manual edits can break the build and are not advised.
 # This file is expected to be part of source control.
 com.jcraft:jsch:0.1.54
+commons-io:commons-io:2.6
 junit:junit:4.12
 org.hamcrest:hamcrest-core:1.3
 org.slf4j:slf4j-api:1.7.25
diff --git a/gradle/dependency-locks/compatTestRuntimeClasspath.lockfile b/gradle/dependency-locks/compatTestRuntimeClasspath.lockfile
index 2e537ab..fb30e45 100644
--- a/gradle/dependency-locks/compatTestRuntimeClasspath.lockfile
+++ b/gradle/dependency-locks/compatTestRuntimeClasspath.lockfile
@@ -3,6 +3,7 @@
 # This file is expected to be part of source control.
 com.athaydes:spock-reports:1.6.0
 com.jcraft:jsch:0.1.54
+commons-io:commons-io:2.6
 junit:junit:4.12
 org.hamcrest:hamcrest-core:1.3
 org.slf4j:slf4j-api:1.7.25
diff --git a/src/compatTest/groovy/org/fidata/gradle/KeygenPluginSpecification.groovy b/src/compatTest/groovy/org/fidata/gradle/KeygenPluginSpecification.groovy
new file mode 100644
index 0000000..f7189dd
--- /dev/null
+++ b/src/compatTest/groovy/org/fidata/gradle/KeygenPluginSpecification.groovy
@@ -0,0 +1,127 @@
+#!/usr/bin/env groovy
+/*
+ * Specification for org.fidata.keygen Gradle plugin
+ * Copyright © 2018  Basil Peace
+ *
+ * This file is part of gradle-keygen-plugin.
+ *
+ * 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.
+ */
+package org.fidata.gradle
+
+import spock.lang.Specification
+import org.gradle.testkit.runner.GradleRunner
+import org.gradle.testkit.runner.BuildResult
+import com.jcraft.jsch.JSch
+import com.jcraft.jsch.KeyPair
+import java.nio.file.Files
+import org.apache.commons.io.FileUtils
+
+/**
+ * Specification for {@link org.fidata.gradle.KeygenPlugin} class
+ */
+class KeygenPluginSpecification extends Specification {
+  // fields
+  boolean success = false
+
+  final File testProjectDir = Files.createTempDirectory('compatTest').toFile()
+
+  File buildFile = new File(testProjectDir, 'build.gradle')
+  File settingsFile = new File(testProjectDir, 'settings.gradle')
+  File propertiesFile = new File(testProjectDir, 'gradle.properties')
+
+  // fixture methods
+
+  // run before the first feature method
+  // void setupSpec() { }
+
+  // run before every feature method
+  void setup() {
+    buildFile << '''\
+      plugins {
+        id 'org.fidata.keygen'
+      }
+    '''.stripIndent()
+  }
+
+  // run after every feature method
+  void cleanup() {
+    /*
+     * WORKAROUND:
+     * Jenkins doesn't set CI environment variable
+     * https://issues.jenkins-ci.org/browse/JENKINS-36707
+     * <grv87 2018-06-27>
+     */
+    if (success || System.getenv().with { containsKey('CI') || containsKey('JENKINS_URL') }) {
+      FileUtils.deleteDirectory(testProjectDir)
+    }
+  }
+
+  // run after the last feature method
+  // void cleanupSpec() { }
+
+  // feature methods
+  void 'generates ssh key by default'() {
+    given: 'project build file'
+    buildFile << '''\
+      keygen {
+        keyType = RSA
+        keySize = 4096
+      }
+      
+      task('generateSSHKey', type: GenerateSSHKeyTask) {
+        privateKeyFile = layout.buildDirectory.file('ssh_key')
+        email = 'test@example.com'
+      }
+    '''.stripIndent()
+
+    when: 'generateSSHKey task is run'
+    build('generateSSHKey')
+
+    then: 'private key file is generated'
+    File privateKeyFile = new File(testProjectDir, 'ssh_key')
+    privateKeyFile.exists()
+
+    and: 'public key file is generated'
+    File publicKeyFile = new File(testProjectDir, 'ssh_key.pub')
+    publicKeyFile.exists()
+
+    when: 'generated key is loaded'
+    JSch jSch = new JSch()
+    KeyPair kpair = KeyPair.load(JSch, privateKeyFile.bytes, publicKeyFile.bytes)
+
+    then: 'no exception is thrown'
+    noExceptionThrown()
+
+    and: 'key type is RSA'
+    kpair.keyType == KeyPair.RSA
+
+    and: 'key length is 4096'
+    privateKeyFile.length() == 4096
+
+    and: 'public key comment is set'
+    kpair.publicKeyComment == 'test@example.com'
+
+    (success = true) != null
+  }
+
+  // helper methods
+  protected BuildResult build(String... arguments) {
+    GradleRunner.create()
+      .withGradleVersion(System.getProperty('compat.gradle.version'))
+      .withProjectDir(testProjectDir)
+      .withArguments([*arguments, '--stacktrace', '--refresh-dependencies'])
+      .withPluginClasspath()
+      .build()
+  }
+}
diff --git a/src/functionalTest/groovy/org/fidata/gradle/KeygenPluginSpecification.groovy b/src/functionalTest/groovy/org/fidata/gradle/KeygenPluginSpecification.groovy
new file mode 100644
index 0000000..9e249d8
--- /dev/null
+++ b/src/functionalTest/groovy/org/fidata/gradle/KeygenPluginSpecification.groovy
@@ -0,0 +1,106 @@
+#!/usr/bin/env groovy
+/*
+ * Specification for org.fidata.keygen Gradle plugin
+ * Copyright © 2018  Basil Peace
+ *
+ * This file is part of gradle-keygen-plugin.
+ *
+ * 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.
+ */
+package org.fidata.gradle
+
+import spock.lang.Specification
+import com.jcraft.jsch.JSch
+import com.jcraft.jsch.KeyPair
+
+/**
+ * Specification for {@link org.fidata.gradle.KeygenPlugin} class
+ */
+class KeygenPluginSpecification extends Specification {
+  // fields
+  final File testProjectDir = Files.createTempDirectory('compatTest').toFile()
+
+  File buildFile = new File(testProjectDir, 'build.gradle')
+  File settingsFile = new File(testProjectDir, 'settings.gradle')
+  File propertiesFile = new File(testProjectDir, 'gradle.properties')
+
+  // fixture methods
+
+  // run before the first feature method
+  // void setupSpec() { }
+
+  // run before every feature method
+  void setup() {
+    project = ProjectBuilder.builder().withProjectDir(testProjectDir.root).build()
+    project.apply plugin: 'org.fidata.keygen'
+  }
+
+  // run after every feature method
+  // void cleanup() { }
+
+  // run after the last feature method
+  // void cleanupSpec() { }
+
+  // feature methods
+  void 'generates ssh key by default'() {
+    given: 'project build file'
+    project.keygen {
+      keyType = RSA
+      keySize = 4096
+    }
+      
+    project.task('generateSSHKey', type: GenerateSSHKeyTask) {
+      privateKeyFile = new File(buildDir, 'ssh_key')
+      email = 'test@example.com'
+    }
+
+    when: 'generateSSHKey task is run'
+    build('generateSSHKey')
+
+    then: 'private key file is generated'
+    File privateKeyFile = new File(testProjectDir, 'ssh_key')
+    privateKeyFile.exists()
+
+    and: 'public key file is generated'
+    File publicKeyFile = new File(testProjectDir, 'ssh_key.pub')
+    publicKeyFile.exists()
+
+    when: 'generated key is loaded'
+    JSch jSch = new JSch()
+    KeyPair kpair = KeyPair.load(JSch, privateKeyFile.bytes, publicKeyFile.bytes)
+
+    then: 'no exception is thrown'
+    noExceptionThrown()
+
+    and: 'key type is RSA'
+    kpair.keyType == KeyPair.RSA
+
+    and: 'key length is 4096'
+    privateKeyFile.length() == 4096
+
+    and: 'public key comment is set'
+    kpair.publicKeyComment == 'test@example.com'
+
+    (success = true) != null
+  }
+
+  // helper methods
+  protected BuildResult build(String... arguments) {
+    GradleRunner.create()
+      .withGradleVersion(System.getProperty('compat.gradle.version'))
+      .withProjectDir(testProjectDir)
+      .withArguments([*arguments, '--stacktrace', '--refresh-dependencies'])
+      .withPluginClasspath()
+      .build()
+  }
+}
diff --git a/src/main/groovy/org/fidata/gradle/KeygenExtension.groovy b/src/main/groovy/org/fidata/gradle/KeygenExtension.groovy
new file mode 100644
index 0000000..d896376
--- /dev/null
+++ b/src/main/groovy/org/fidata/gradle/KeygenExtension.groovy
@@ -0,0 +1,37 @@
+#!/usr/bin/env groovy
+/*
+ * KeygenConvention class
+ * Copyright © 2018  Basil Peace
+ *
+ * This file is part of gradle-keygen-plugin.
+ *
+ * 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.
+ */
+package org.fidata.gradle
+
+import com.jcraft.jsch.KeyPair
+
+class KeygenExtension {
+  static final int DSA = KeyPair.DSA
+  static final int RSA = KeyPair.RSA
+  static final int ECDSA = KeyPair.ECDSA
+  /**
+   * Type of the key. See constants in {@link KeyPair} for valid values
+   */
+  int keyType = RSA
+
+  /**
+   * Type of the key
+   */
+  int keySize = 4096
+}
diff --git a/src/main/groovy/org/fidata/gradle/KeygenPlugin.groovy b/src/main/groovy/org/fidata/gradle/KeygenPlugin.groovy
index 756ef29..dd3287e 100644
--- a/src/main/groovy/org/fidata/gradle/KeygenPlugin.groovy
+++ b/src/main/groovy/org/fidata/gradle/KeygenPlugin.groovy
@@ -22,13 +22,15 @@
 import groovy.transform.CompileStatic
 import org.gradle.api.Plugin
 import org.gradle.api.Project
+import org.fidata.gradle.tasks.GenerateSSHKeyTask
 
 /**
  * Provides an environment for a general, language-agnostic project
  */
 @CompileStatic
 final class KeygenPlugin implements Plugin<Project> {
-  @SuppressWarnings(['EmptyMethod', 'UnusedMethodParameter'])
   void apply(Project project) {
+    project.extensions.create 'keygen', KeygenExtension
+    project.extensions.extraProperties['GenerateSSHKeyTask'] = GenerateSSHKeyTask
   }
 }
diff --git a/src/main/groovy/org/fidata/gradle/tasks/GenerateSSHKeyTask.groovy b/src/main/groovy/org/fidata/gradle/tasks/GenerateSSHKeyTask.groovy
index d409456..92c586a 100644
--- a/src/main/groovy/org/fidata/gradle/tasks/GenerateSSHKeyTask.groovy
+++ b/src/main/groovy/org/fidata/gradle/tasks/GenerateSSHKeyTask.groovy
@@ -17,9 +17,17 @@
  * implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
+package org.fidata.gradle.tasks
+
 import com.jcraft.jsch.JSch
 import com.jcraft.jsch.KeyPair
+import groovy.transform.CompileStatic
+import org.fidata.gradle.KeygenExtension
 import org.gradle.api.DefaultTask
+import org.gradle.api.file.RegularFile
+import org.gradle.api.file.RegularFileProperty
+import org.gradle.api.provider.Property
+import org.gradle.api.provider.Provider
 import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.TaskAction
@@ -27,40 +35,34 @@
 /**
  * Task to generate SSH key
  */
+@CompileStatic
 class GenerateSSHKeyTask extends DefaultTask {
   private final static JSch JSCH = new JSch()
 
-  private File privateKeyFile
-  private File publicKeyFile
-
   /**
-   * @return private key file
+   * Private key file
    */
   @OutputFile
-  File getPrivateKeyFile() { privateKeyFile }
+  final RegularFileProperty privateKeyFile = newOutputFile()
   /**
-   * @param privateKeyFile private key file
-   */
-  void setPrivateKeyFile(File privateKeyFile) {
-    this.privateKeyFile = privateKeyFile
-    this.publicKeyFile = project.file("${ privateKeyFile }.pub")
-  }
-  /**
-   * @return public key file
+   * Public key file
    */
   @OutputFile
-  File getPublicKeyFile() { publicKeyFile }
+  final Provider<RegularFile> publicKeyFile = project.layout.projectDirectory.file(project.provider({ "${ privateKeyFile.get()?.asFile }.pub" }))
 
+  static final int DSA = KeyPair.DSA
+  static final int RSA = KeyPair.RSA
+  static final int ECDSA = KeyPair.ECDSA
   /**
    * Type of the key. See constants in {@link KeyPair} for valid values
    */
   @Input
-  int keyType = KeyPair.RSA
+  final Property<Integer> keyType = project.objects.property(Integer)
   /**
-   * Type of the key
+   * Size of the key
    */
   @Input
-  int keySize = 4096
+  final Property<Integer> keySize = project.objects.property(Integer)
   /**
    * Email to add to public key as comment
    */
@@ -69,7 +71,7 @@
 
   GenerateSSHKeyTask() {
     onlyIf {
-      !privateKeyFile.exists() || !publicKeyFile.exists()
+      !privateKeyFile.get().asFile.exists() || !publicKeyFile.get().asFile.exists()
     }
   }
 
@@ -78,9 +80,10 @@
    */
   @TaskAction
   void generate() {
-    KeyPair kpair = KeyPair.genKeyPair(JSCH, keyType, keySize)
-    kpair.writePrivateKey(privateKeyFile.path)
-    kpair.writePublicKey(publicKeyFile.path, email)
+    KeygenExtension keygenExtension = project.extensions.getByType(KeygenExtension)
+    KeyPair kpair = KeyPair.genKeyPair(JSCH, keyType.getOrElse(keygenExtension.keyType), keySize.getOrElse(keygenExtension.keySize))
+    kpair.writePrivateKey(privateKeyFile.get().asFile.path)
+    kpair.writePublicKey(publicKeyFile.get().asFile.path, email)
     kpair.dispose()
   }
 }
diff --git a/src/main/java/org/fidata/gradle/tasks/package-info.java b/src/main/java/org/fidata/gradle/tasks/package-info.java
new file mode 100644
index 0000000..5affb77
--- /dev/null
+++ b/src/main/java/org/fidata/gradle/tasks/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * org.fidata.gradle.tasks Package Info
+ * Copyright © 2018  Basil Peace
+ *
+ * This file is part of gradle-keygen-plugin.
+ *
+ * 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.
+ */
+/**
+ * Gradle tasks developed by FIDATA
+ */
+package org.fidata.gradle.tasks;