当前位置: 首页 > 面试题库 >

如何在Go中正确编写JVM AES / CFB8加密

奚飞星
2023-03-14
问题内容

我在Kotlin中编写了一个小测试,以使用带有算法“ AES / CFB8 / NoPadding”的Cipher实例加密一些文本“
Hello”。(Minecraft的东西)

我现在正尝试在Go中执行相同的操作,但是我无法产生相同的结果。我尝试过的所有不同方法都会产生不同的结果。

这些是我已经浏览过的以下线程/示例,以达到这一点。

  1. 如何在Golang中使用RSA密钥对进行AES加密和解密
  2. https://play.golang.org/p/77fRvrDa4A
  3. 在Golang中解密在Python AES CFB中加密的内容
  4. https://gist.github.com/temoto/5052503
  5. 使用AES-CFB时Go和Pycrypto的结果不同

Kotlin代码:

enum class Mode(val mode: Int)
{

    ENCRYPT(Cipher.ENCRYPT_MODE),
    DECRYPT(Cipher.DECRYPT_MODE),
}

fun createSecret(data: String): SecretKey
{
    return SecretKeySpec(data.toByteArray(), "AES")
}

fun newCipher(mode: Mode): Cipher
{
    val secret = createSecret("qwdhyte62kjneThg")
    val cipher = Cipher.getInstance("AES/CFB8/NoPadding")
    cipher.init(mode.mode, secret, IvParameterSpec(secret.encoded))

    return cipher
}

fun runCipher(data: ByteArray, cipher: Cipher): ByteArray
{
    val output = ByteArray(data.size)

    cipher.update(data, 0, data.size, output)

    return output
}


fun main()
{
    val encrypter = newCipher(Mode.ENCRYPT)
    val decrypter = newCipher(Mode.DECRYPT)

    val iText = "Hello"
    val eText = runCipher(iText.toByteArray(), encrypter)
    val dText = runCipher(eText, decrypter)
    val oText = String(dText)


    println(iText)
    println(Arrays.toString(eText))
    println(Arrays.toString(dText))
    println(oText)
}

验证码:

func TestCipher(t *testing.T) {

    secret := newSecret("qwdhyte62kjneThg")

    encrypter := newCipher(secret, ENCRYPT)
    decrypter := newCipher(secret, DECRYPT)

    iText := "Hello"
    eText := encrypter.run([]byte(iText))
    dText := decrypter.run(eText)
    oText := string(dText)

    fmt.Printf("%s\n%v\n%v\n%s\n", iText, eText, dText, oText)
}

type Mode int

const (
    ENCRYPT Mode = iota
    DECRYPT
)

type secret struct {
    Data []byte
}

type cipherInst struct {
    Data cipher2.Block
    Make cipher2.Stream
}

func newSecret(text string) *secret {
    return &secret{Data: []byte(text)}
}

func newCipher(data *secret, mode Mode) *cipherInst {
    cip, err := aes.NewCipher(data.Data)
    if err != nil {
        panic(err)
    }

    var stream cipher2.Stream

    if mode == ENCRYPT {
        stream = cipher2.NewCFBEncrypter(cip, data.Data)
    } else {
        stream = cipher2.NewCFBDecrypter(cip, data.Data)
    }

    return &cipherInst{Data: cip, Make: stream}
}

func (cipher *cipherInst) run(dataI []byte) []byte {

    out := make([]byte, len(dataI))
    cipher.Make.XORKeyStream(out, dataI)

    return out
}

Kotlin代码产生输出:

Hello
[68, -97, 26, -50, 126]
[72, 101, 108, 108, 111]
Hello

但是,Go代码会产生输出:

Hello
[68 97 242 158 187]
[72 101 108 108 111]
Hello

在这一点上,这个问题已经使我正在从事的项目的进度几乎停止了。关于我所缺少或做错的任何信息都将有所帮助。


问题答案:

解决方案是手动实施CFB8,因为内置实施默认为CFB128。

由kostya创建并由IlmariKaronen修复的实现。

如果有人正在寻找分段大小= 8的Go实现CFB模式,则可以使用以下方法:

import "crypto/cipher"

// CFB stream with 8 bit segment size
// See http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
type cfb8 struct {
    b         cipher.Block
    blockSize int
    in        []byte
    out       []byte

    decrypt bool
}

func (x *cfb8) XORKeyStream(dst, src []byte) {
    for i := range src {
        x.b.Encrypt(x.out, x.in)
        copy(x.in[:x.blockSize-1], x.in[1:])
        if x.decrypt {
            x.in[x.blockSize-1] = src[i]
        }
        dst[i] = src[i] ^ x.out[0]
        if !x.decrypt {
            x.in[x.blockSize-1] = dst[i]
        }
    }
}

// NewCFB8Encrypter returns a Stream which encrypts with cipher feedback mode
// (segment size = 8), using the given Block. The iv must be the same length as
// the Block's block size.
func newCFB8Encrypter(block cipher.Block, iv []byte) cipher.Stream {
    return newCFB8(block, iv, false)
}

// NewCFB8Decrypter returns a Stream which decrypts with cipher feedback mode
// (segment size = 8), using the given Block. The iv must be the same length as
// the Block's block size.
func newCFB8Decrypter(block cipher.Block, iv []byte) cipher.Stream {
    return newCFB8(block, iv, true)
}

func newCFB8(block cipher.Block, iv []byte, decrypt bool) cipher.Stream {
    blockSize := block.BlockSize()
    if len(iv) != blockSize {
        // stack trace will indicate whether it was de or encryption
        panic("cipher.newCFB: IV length must equal block size")
    }
    x := &cfb8{
        b:         block,
        blockSize: blockSize,
        out:       make([]byte, blockSize),
        in:        make([]byte, blockSize),
        decrypt:   decrypt,
    }
    copy(x.in, iv)

    return x
}


 类似资料:
  • 我对编码很陌生。尝试用Java编写一个evaluatePostfix函数。我不断得到一个错误: 不兼容的类型:int不能转换为字符堆栈。push(eval(token,a,b)); 下面是我的代码块: 函数接受后缀表达式并计算结果。 这是我的eval函数:

  • 问题内容: 当我在Python中打开FIFO(命名管道)进行写入时,发生了非常奇怪的事情。考虑一下当我尝试打开FIFO以便在交互式解释器中进行写入时发生的情况: 以上行将阻塞,直到我打开另一个解释器并键入以下内容: 我不明白为什么我必须等待打开管道进行读取,但是让我们跳过它。上面的代码将阻塞,直到有可用的数据为止。但是,假设我回到第一个解释器窗口并输入: 预期的行为是,在第二个解释器上,对的调用将

  • 听起来有点愚蠢,但我需要我的方法的帮助,这很烦人。我试着在网上查找,因为是一个出错和“找不到Kid constructor#2”的程序,尽管它在那里,我甚至会做其他事情,但它不起作用。好吧,这太多了,下面是我的代码: 好的,所以我上面的toString(我知道,我的第三个参数是关闭的,应该是字符串)是关闭的。如果我硬编码第三个值,它就会失控,说它找不到这个(上面)。那么我怎么才能得到日期并把它分开

  • 问题内容: 在python中,我们使用反斜杠表示当前语句继续到下一行 例如, 或者简单地说, 可以用Go语言做到这一点吗?谢谢 问题答案: 当然可以,只需将运算符放在最后,例如: 另请注意,不可能在操作员之前中断换行。以下代码 无效 : 该规则在此处和规范中进行了描述。

  • 问题内容: 是否有合法的方式写下我打算以后编写完整测试功能的测试用例?就像即将进行的mochajs测试一样? 问题答案: 软件包文档使用以下示例描述了这样的示例: 如果不适用于调用 T和 B的Skip方法,则可以跳过测试和基准测试: 如果您启动带有标志的消息,则将打印您提供的消息(在此示例中,您还需要提供标志以查看跳过消息)。

  • 我想从这个表中获取所有数据,因为我正在使用查询: 它没有给我任何结果。我是php新手,有人能帮我解决这个问题吗?