Используйте RSA между Android и Go - PullRequest
1 голос
/ 13 октября 2019

В проекте чата с go and android я хочу использовать RSA для шифрования

Я нашел решение в этот вопрос , и поиск работы, но мне нужно поменять приватный и публичныйключ для каждого пользователя!

Как создать закрытый и открытый ключ для отправки на андроид?

Я пытаюсь разными способами, но в Android выдает ошибку, когда я хочу разобрать открытый ключ Android

    public static PublicKey stringToPublicKeytoserver(String publicKeyString)
    {
        try {
            publicKeyString = publicKeyString.replace("-----BEGIN PUBLIC KEY-----", "");
            publicKeyString = publicKeyString.replace("-----END PUBLIC KEY-----", "");
            byte[] keyBytes = Base64.decode(publicKeyString, Base64.DEFAULT);
            X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA);
            serveruk=keyFactory.generatePublic(spec);
            return serveruk;
        } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
            e.printStackTrace();
            return null;
        }
    }

Ошибка Android

java.security.spec.InvalidKeySpecException: com.android.org.conscrypt.OpenSSLX509CertificateFactory $ ParsingException: Ошибка синтаксического анализа открытого ключа

Key Generation

   // Generate RSA Keys
   miryanPrivateKey, err := rsa.GenerateKey(rand.Reader, 1024)
   fatal(err)


   // save PEM file
   pemfile, err := os.Create("public.pem")

   if err != nil {
       fmt.Println(err)
       os.Exit(1)
   }

   //publi := &miryanPrivateKey.PublicKey

   // http://golang.org/pkg/encoding/pem/#Block

   var pemkey = &pem.Block{
       Type : "PUBLIC KEY",
       Bytes : x509.MarshalPKCS1PublicKey(&miryanPrivateKey.PublicKey)}

   err = pem.Encode(pemfile, pemkey)

   if err != nil {
       fmt.Println(err)
       os.Exit(1)
   }

   pemfile.Close()
   //and even i use function to convert toPKCS8
   byt, _:= MarshalPKCS8PublicKey(&miryanPrivateKey.PublicKey)

   var pemkey = &pem.Block{
       Type : "PUBLIC KEY",
       Bytes : byt}

   func MarshalPKCS8PublicKey(key *rsa.PublicKey) ([]byte, error) {
   var pkey PKCS8Key
   pkey.Version = 0
   pkey.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 1)
   pkey.PrivateKeyAlgorithm[0] = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
   pkey.PrivateKey = x509.MarshalPKCS1PublicKey(key)
   return asn1.Marshal(pkey)
}

Я думаю, что моя главная проблема заключается в том, чтобы использовать pkcs1, но использовать android pkcs8

public.pem

-----BEGIN PUBLIC KEY-----
MIGfAgEAMAsGCSqGSIb3DQEBAQSBjDCBiQKBgQDh1jHGdbo/QLeA1y5lC2YSSoal
hPBLWxz7OYpNj5pZDcuqrJFfhEvv1CGvBR0bKB/3hTpUYAPiswI+OH2BcHks0+Ef
N/KZYjPQQsB1gJByENTPvdQwlDIJVW8cDhij7jMMwq/TOs+ijudCUojcfvkJ5Zvf
BJB6g0ucg580W98K4wIDAQAB
-----END PUBLIC KEY-----

1 Ответ

1 голос
/ 16 октября 2019

Я исправляю это!

Я генерирую открытый и закрытый ключ с этим кодом Go:

/*
 * Genarate rsa keys.
*/

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/gob"
    "encoding/pem"
    "fmt"
    "os"
)

func main() {
    reader := rand.Reader
    bitSize := 2048

    key, err := rsa.GenerateKey(reader, bitSize)
    checkError(err)

    publicKey := key.PublicKey

    saveGobKey("private.key", key)
    savePEMKey("private.pem", key)

    saveGobKey("public.key", publicKey)
    savePublicPEMKey("public.pem", publicKey)
}

func saveGobKey(fileName string, key interface{}) {
    outFile, err := os.Create(fileName)
    checkError(err)
    defer outFile.Close()

    encoder := gob.NewEncoder(outFile)
    err = encoder.Encode(key)
    checkError(err)
}

func savePEMKey(fileName string, key *rsa.PrivateKey) {
    outFile, err := os.Create(fileName)
    checkError(err)
    defer outFile.Close()

    var privateKey = &pem.Block{
        Type:  "PRIVATE KEY",
        Bytes: x509.MarshalPKCS1PrivateKey(key),
    }

    err = pem.Encode(outFile, privateKey)
    checkError(err)
}

func savePublicPEMKey(fileName string, pubkey rsa.PublicKey) {
    asn1Bytes, err := x509.MarshalPKIXPublicKey(&pubkey)
    checkError(err)

    var pemkey = &pem.Block{
        Type:  "PUBLIC KEY",
        Bytes: asn1Bytes,
    }

    pemfile, err := os.Create(fileName)
    checkError(err)
    defer pemfile.Close()

    err = pem.Encode(pemfile, pemkey)
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        fmt.Println("Fatal error ", err.Error())
        os.Exit(1)
    }
}

, а затем зашифровываю свое сообщение в Android с помощью сгенерированного открытого ключа в GO:

static PublicKey serveruk;


public final static String chi="RSA/ECB/OAEPPadding";

public final static String RSA = "RSA";

private final static int CRYPTO_BITS = 512;


String pubPEM = "public key from public.pem";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    stringToPublicKeytoserver(pubPEM);
    Log.e("ENCODED", enc4golang("Please hide me !"));

}


public static PublicKey stringToPublicKeytoserver(String publicKeyString)
{
    try {
        publicKeyString = publicKeyString.replace("-----BEGIN PUBLIC KEY-----", "");
        publicKeyString = publicKeyString.replace("-----END PUBLIC KEY-----", "");
        byte[] keyBytes = Base64.decode(publicKeyString, Base64.DEFAULT);
        X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        serveruk=keyFactory.generatePublic(spec);
        return serveruk;
    } catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
        e.printStackTrace();
        return null;
    }
}


private static byte[] enc4golang(String text, PublicKey pubRSA) throws Exception{
    Cipher cipher = Cipher.getInstance(chi);
    cipher.init(Cipher.ENCRYPT_MODE, pubRSA);
    return cipher.doFinal(text.getBytes("UTF-8")); //i also advice you to use: .getBytes("UTF-8"); instead of data.getBytes();
}


public final static String enc4golang(String text){
    try {
        return Base64.encodeToString(enc4golang(text, serveruk) ,Base64.DEFAULT);  //send this string to golang
    }
    catch(Exception e)
    {
        e.printStackTrace();
    }
    return null;
}

и затем я расшифровываю его с помощью кода GO:

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/sha1"
    "crypto/x509"
    "encoding/base64"
    "encoding/pem"
)

func main(){

    const priPEM = `private key from private.pem`

    const pubPEM = `public key from public.pem`

    base64DecodeBytes, err := base64.StdEncoding.DecodeString("encrypted data from android")
    if err != nil {
        panic(err)
    }
    privateKeyBlock, _ := pem.Decode([]byte(priPEM))
    var pri *rsa.PrivateKey
    pri, parseErr := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
    if parseErr != nil {
        panic(parseErr)
    }
    decryptedData, decryptErr := rsa.DecryptOAEP(sha1.New(), rand.Reader, pri, base64DecodeBytes, nil)
    if decryptErr != nil {
        panic(decryptErr)
    }

    print(string(decryptedData))

}
...