Skip to content

Instantly share code, notes, and snippets.

@mumoshu
Created January 10, 2012 06:08
Show Gist options
  • Save mumoshu/1587327 to your computer and use it in GitHub Desktop.
Save mumoshu/1587327 to your computer and use it in GitHub Desktop.
DES and AES encryption in Scala
name := "DES and AES encryption in Scala"
version := "1.0"
scalaVersion := "2.9.1"
libraryDependencies += "commons-codec" % "commons-codec" % "1.6"
package protocol {
import annotation.implicitNotFound
import java.io.{DataOutputStream, ByteArrayOutputStream}
@implicitNotFound(msg = "Could not find a Writes for ${T}")
trait Writes[T] {
def writes(value: T): Array[Byte]
}
class DataOutputStreamWrites[T](writeValue: (DataOutputStream, T) => Unit) extends Writes[T] {
def writes(value: T): Array[Byte] = {
val bos = new ByteArrayOutputStream
val dos = new DataOutputStream(bos)
writeValue(dos, value)
dos.flush()
val byteArray = bos.toByteArray
bos.close()
byteArray
}
}
object defaults {
implicit object WritesString extends Writes[String] {
def writes(value: String) = value.getBytes("UTF-8")
}
implicit object WritesLong extends DataOutputStreamWrites[Long](_.writeLong(_))
implicit object WritesInt extends DataOutputStreamWrites[Int](_.writeInt(_))
implicit object WritesShort extends DataOutputStreamWrites[Short](_.writeShort(_))
}
}
package crypto {
import protocol.Writes
import javax.crypto.spec.SecretKeySpec
import javax.crypto.Cipher
trait Encryption {
def encrypt(dataBytes: Array[Byte], secret: String): Array[Byte]
def decrypt(codeBytes: Array[Byte], secret: String): Array[Byte]
def encrypt[T:Writes](data: T, secret: String): Array[Byte] = encrypt(implicitly[Writes[T]].writes(data), secret)
}
class JavaCryptoEncryption(algorithmName: String) extends Encryption {
def encrypt(bytes: Array[Byte], secret: String): Array[Byte] = {
val secretKey = new SecretKeySpec(secret.getBytes("UTF-8"), algorithmName)
val encipher = Cipher.getInstance(algorithmName + "/ECB/PKCS5Padding")
encipher.init(Cipher.ENCRYPT_MODE, secretKey)
encipher.doFinal(bytes)
}
def decrypt(bytes: Array[Byte], secret: String): Array[Byte] = {
val secretKey = new SecretKeySpec(secret.getBytes("UTF-8"), algorithmName)
val encipher = Cipher.getInstance(algorithmName + "/ECB/PKCS5Padding")
encipher.init(Cipher.DECRYPT_MODE, secretKey)
encipher.doFinal(bytes)
}
}
object DES extends JavaCryptoEncryption("DES")
object AES extends JavaCryptoEncryption("AES")
}
object Main extends App {
import org.apache.commons.codec.binary.Base64
import crypto._
import protocol.defaults._
def encodeBase64(bytes: Array[Byte]) = Base64.encodeBase64String(bytes)
println(encodeBase64(DES.encrypt("hoge", "01234567")))
//=> vyudTtnBJfs=
println(encodeBase64(AES.encrypt("hoge", "0123456789012345")))
//=> QWSouZUMVYMfS86xFyBgtQ==
println(encodeBase64(DES.encrypt(123L, "01234567")))
//=> Cqw2ipxTtvIIu122s3wG1w==
println(encodeBase64(DES.encrypt(123, "01234567")))
//=> BV+LSCSYmUU=
}
@khalid-saifullah
Copy link

Dear KUOKA, really an excellent snippet. I have successfully used both encryption and decryption using your code. Now, I want to use similar approach to encrypt data in PHP so that I can open my code through an API. Problem is, PHP AES encryption is talking about a key and a initial vector (IV). But your code only use one key. Any suggestion?

Thanks in Advance
Khalid

@metaweta
Copy link

metaweta commented Oct 1, 2013

You're encrypting using ECB mode, which is a big no-no. See http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29

@Richard-W
Copy link

@khalid-saifullah: This code snippet uses ECB mode, which is considered insecure for most applications. PHP uses CBC which randomizes the output of the cipher but needs an initialization vector.

I have implemented a similar wrapper (https://github.com/Richard-W/scalacrypt), which uses CBC mode and is therefore compatible with PHP. The first 16 bytes of the output of the AES ciphers in scalacrypt are the IV. You can just slice them of and supply them to the PHP function.

@Shazankk
Copy link

will this generate new encryption key for same value when triggered always ?
say for example encrypt("hello") => =124sff14vdb
if again the same hello is encountered as another entry will that give the same output or a new key will be generated. ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment