Last active
December 16, 2015 22:59
-
-
Save andrewconner/5510961 to your computer and use it in GitHub Desktop.
UserVoice SSO Token Generator in Scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.apache.commons.codec.net.URLCodec | |
import org.apache.commons.codec.binary.Base64 | |
import javax.crypto.spec.SecretKeySpec | |
import javax.crypto.spec.IvParameterSpec | |
import org.apache.commons.codec.digest.DigestUtils | |
import java.io.InputStream | |
import java.io.OutputStream | |
import javax.crypto.Cipher | |
import javax.crypto.CipherOutputStream | |
import java.io.ByteArrayOutputStream | |
import java.io.ByteArrayInputStream | |
object UserVoiceTokenGenerator { | |
private final val USERVOICE_SUBDOMAIN = "<insert UserVoice subdomain>" | |
private final val SSO_KEY = "<insert UserVoice SSO key>" | |
private final val INIT_VECTOR = "OpenSSL for Ruby".getBytes() | |
private val hash = DigestUtils.sha(SSO_KEY + USERVOICE_SUBDOMAIN).toSeq | |
private val secretKeySpec = new SecretKeySpec(hash.take(16).toArray, "AES") | |
private val ivSpec = new IvParameterSpec(INIT_VECTOR) | |
private val urlCodec = new URLCodec("ASCII") | |
private val base64 = new Base64() | |
private def encrypt(in: InputStream): ByteArrayOutputStream = { | |
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") | |
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivSpec) | |
val buf = new Array[Byte](1024) | |
val byteStream = new ByteArrayOutputStream() | |
val out = new CipherOutputStream(byteStream, cipher) | |
try { | |
Iterator.continually(in.read(buf)).takeWhile(_ >= 0) foreach { numRead => | |
out.write(buf, 0, numRead) | |
} | |
} catch { | |
case ex: Throwable => | |
// integrate your application logging | |
ex.printStackTrace() | |
} finally { | |
out.close() | |
} | |
byteStream | |
} | |
def create(json: String): String = { | |
val jsonBytes = json.getBytes() | |
val data = INIT_VECTOR.zip(jsonBytes).take(16).map({ case (i, d) => (i ^ d).byteValue }) ++ jsonBytes.drop(INIT_VECTOR.length) | |
val out = encrypt(new ByteArrayInputStream(data)); | |
new String(urlCodec.encode(base64.encode(out.toByteArray))) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment